Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将嵌套对象数组扩展为路径数组的最快方法(lodash)_Javascript_Json_Lodash - Fatal编程技术网

Javascript 将嵌套对象数组扩展为路径数组的最快方法(lodash)

Javascript 将嵌套对象数组扩展为路径数组的最快方法(lodash),javascript,json,lodash,Javascript,Json,Lodash,我有一个查询语法,需要应用于json对象,并在json对象中返回一个有效路径数组 例如,对于这样的查询: People.[].Dependents.[] 以及以下JSON对象: { "People": [ { "FirstName": "John", "LastName": "Doe", "Dependents": [ { "N

我有一个查询语法,需要应用于json对象,并在json对象中返回一个有效路径数组

例如,对于这样的查询:

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;i另一个镜头:)

var=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);