Javascript 将嵌套对象数组扩展为路径数组的最快方法(lodash)
我有一个查询语法,需要应用于json对象,并在json对象中返回一个有效路径数组 例如,对于这样的查询:Javascript 将嵌套对象数组扩展为路径数组的最快方法(lodash),javascript,json,lodash,Javascript,Json,Lodash,我有一个查询语法,需要应用于json对象,并在json对象中返回一个有效路径数组 例如,对于这样的查询: People.[].Dependents.[] 以及以下JSON对象: { "People": [ { "FirstName": "John", "LastName": "Doe", "Dependents": [ { "N
People.[].Dependents.[]
以及以下JSON对象:
{
"People": [
{
"FirstName": "John",
"LastName": "Doe",
"Dependents": [
{
"Name": "John First Dep"
},
{
"Name": "John Second Dep"
}
]
},
{
"FirstName": "Jane",
"LastName": "Smith",
"Dependents": [
{
"Name": "Jane First Dep"
}
]
}
]
}
结果将是:
[
"People.0.Dependents.0",
"People.0.Dependents.1",
"People.1.Dependents.0",
]
我目前正试图尽可能简洁地做到这一点。到目前为止,我所做的任何尝试都会产生太多的代码,并且难以置信地难以遵循。我错过了什么明显的东西吗
编辑:当前代码:
function expandQuery(data, path) {
const parts = path.split("[]").map(s => _.trim(s, "."));
const [outer, ...right] = parts;
const inner = _.join(right, ".[].");
let groupData = _.get(data, outer, []);
if (!_.isArray(groupData)) {
groupData = [groupData];
}
const groupLength = groupData.length;
let items = [];
for (let ind = 0; ind < groupLength; ind++) {
items.push(outer + "." + ind.toString() + "." + inner);
}
const result = [];
for (let ind = 0; ind < items.length; ind++) {
const item = items[ind];
if (item.includes("[]")) {
result.push(...expandQuery(data, item));
} else {
result.push(_.trim(item, "."));
}
}
return result;
}
函数expandQuery(数据、路径){
const parts=path.split(“[]”).map(s=>;
常数[外部,…右侧]=零件;
const inner=u.join(右,“.[]”);
让groupData=551;.get(data,outer,[]);
如果(!.isArray(groupData)){
groupData=[groupData];
}
const groupLength=groupData.length;
设项目=[];
for(设ind=0;ind
我特别想把它缩短。这是您想要的,但并不比您的解决方案简单/短
function getPaths (collection, query) {
let tokens = query.split(".")
function walkPath (collection, [currentToken, ...restTokens], paths) {
if (!currentToken) { // no more tokens to follow
return paths.join(".")
}
if (currentToken === "[]") { // iterate array
const elemPaths = _.range(collection.length)
return elemPaths.map(elemPath => walkPath(collection[elemPath], restTokens, [...paths, elemPath]))
}
else {
return walkPath(collection[currentToken], restTokens, [...paths, currentToken])
}
}
return _.flattenDeep(walkPath(collection, tokens, []))
}
它还缺少错误处理。这可能对您有一些用处。要展平深度嵌套的数组,您可以使用
。.flattedeep
。
但是,如果您不介意离开lodash,您可以执行以下操作:
函数getNextToken(路径){
让token=path.trim();
让我们休息吧;
const separatorPos=path.indexOf('.');
如果(separatorPos>-1){
token=path.substr(0,separatorPos.trim();
rest=path.substr(separatorPos+1.trim();
}
返回{token,rest};
}
const expandQuery=(数据,路径)=>{
常量展开=(数据、路径、已找到=[])=>{
如果(数据===未定义){
返回[];
}
const{token,rest}=getNextToken(路径);
交换机(令牌){
//走到路的尽头
案例“”:
return[found.join('.');
//得到一个数组
案例“[]”:
if(data.constructor!==数组){
返回[];
}
const foundpath=[];
让我;
对于(i=0;ivar=require('lodash');
var测试={
“人”:[
{
“名字”:“约翰”,
“姓氏”:“能源部”,
“家属”:[
{
“姓名”:“John First Dep”
},
{
“姓名”:“约翰第二副总裁”
}
]
},
{
“名字”:“简”,
“姓氏”:“史密斯”,
“家属”:[
{
“姓名”:“Jane First Dep”
}
]
}
]
}
函数映射器(对象、前缀、路径){
如果(事物){
_.forEach(thing,function(value,key){mapper(value,prefix+key+',path);});
}否则如果(uu.isArray(东西)){
对于(var i=0;i
我也要试一试,注意当您使用.get(object,'path.with.point')
并且您的对象键名中有点时,您的代码将中断,我更喜欢使用.get(object,['path','with','point])
const data={“People”:[{“FirstName”:“John”,“LastName”:“Doe”,“Dependents”:[{“Name”:“John First Dep”,“a”:[1,2]},{“Name”:“John Second Dep”,“a”:[3]}}},{“FirstName”:“Jane”,“LastName”:“Smith”,“Dependents”:[{“Name”:“Jane First Dep”,“a”:[1]}]}}};
常数展平=arr=>
arr.reduce((结果,项目)=>result.concat(项目))
常量数组={}
常量getPath=(对象,路径)=>{
const recur=(结果、路径、项、索引)=>{
if(path.length==索引){
返回result.concat(路径)
}
如果(项目===未定义){
抛出新错误(“错误路径”)
}
if(路径[索引]==数组){
const start=path.slice(0,索引)
const end=path.slice(索引+1,path.length)
返回项.map((u1;,i)=>
重现(结果、开始、结束、项目、索引)
)
}
返回重复(结果、路径、项[路径[索引]、索引+1)
}
常量结果=重复([],路径,对象,0)
const levels=path.filter(item=>item==ARRAY).length-1
返回级别>0
?[…新阵列(级别)]。减少(展平,结果)
:结果
}
console.log(
getPath(数据,['People',数组,'Dependents',数组,'a',数组])
)
到目前为止您的尝试是什么?@lumio:添加了一个工作样本哦。。。除了\uu0.range
之外,我喜欢这个解决方案!:)这是一个数量级
var _ = require('lodash');
var test = {
"People": [
{
"FirstName": "John",
"LastName": "Doe",
"Dependents": [
{
"Name": "John First Dep"
},
{
"Name": "John Second Dep"
}
]
},
{
"FirstName": "Jane",
"LastName": "Smith",
"Dependents": [
{
"Name": "Jane First Dep"
}
]
}
]
}
function mapper(thing, prefix, paths) {
if (_.isObject(thing)) {
_.forEach(thing, function(value, key) {mapper(value, prefix+key+'.', paths);});
} else if (_.isArray(thing)) {
for (var i = 0; i < thing.length; i++) mapper(value, prefix+i+'.', paths);
} else {
paths.push(prefix.replace(/\.$/, ''));
}
}
var query = 'People.[].Dependents.[]';
var paths = [];
var results;
query = new RegExp(query.replace(/\[\]/g,'\\d'));
mapper(test, '', paths); // Collect all paths
results = _.filter(paths, function(v) {return query.test(v);}); // Apply query
console.log(results);