如何使用 JavaScript/Prototype 1.7 递归搜索对象树并根据键/值返回匹配对象

发布于 2024-10-27 00:58:17 字数 647 浏览 1 评论 0原文

我有一些嵌套对象数据,我想搜索它并根据 id 返回匹配的对象。

var data = [{id: 0, name: 'Template 0', subComponents:[
        {id: 1, name: 'Template 1', subItems:[
            {id: 2, name: 'Template 2', subComponents:[{id: 3, name: 'Template 3'}], subItems: [{id: 4, name: 'Template 4'}]}
        ]}
    ]}
];

所以我想做这样的事情

getObjectByKeyValue({id: 3}) 

并让它返回,

{id: 3, name: 'Template 3'}

这有点必须一般完成,因为我有子项和子组件,每个子组件都可以有子项。

我使用 Prototype 1.7 尝试过,但没有成功 - 我认为这只是搜索一个数组,而不是一个带有子节点的树:

data.find(function(s){return s.id == 4;})

提前致谢!

I've got some nested object data and I want to search it and return the matching object based on the id.

var data = [{id: 0, name: 'Template 0', subComponents:[
        {id: 1, name: 'Template 1', subItems:[
            {id: 2, name: 'Template 2', subComponents:[{id: 3, name: 'Template 3'}], subItems: [{id: 4, name: 'Template 4'}]}
        ]}
    ]}
];

So I want to do something like this

getObjectByKeyValue({id: 3}) 

and have it return

{id: 3, name: 'Template 3'}

It's sort of got to be done generically because I have subItems, AND subComponents which could each have children.

I tried this using Prototype 1.7 and no luck - I think this just searches an array, and not a tree with it's sub nodes:

data.find(function(s){return s.id == 4;})

Thanks in advance!!!!!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

白云悠悠 2024-11-03 00:58:17

我采用了稍微不同的路线,并将 findKey 方法设置为对象原型:

Object.prototype.findKey = function(keyObj) {
    var p, key, val, tRet;
    for (p in keyObj) {
        if (keyObj.hasOwnProperty(p)) {
            key = p;
            val = keyObj[p];
        }
    }

    for (p in this) {
        if (p == key) {
            if (this[p] == val) {
                return this;
            }
        } else if (this[p] instanceof Object) {
            if (this.hasOwnProperty(p)) {
                tRet = this[p].findKey(keyObj);
                if (tRet) { return tRet; }
            }
        }
    }

    return false;
};

您可以直接在数据对象上调用该方法,并传入您要查找的键/值:

data.findKey({ id: 3 });

请注意,此函数允许您根据任意键查找对象:

data.findKey({ name: 'Template 0' });

查看示例 → (打开控制台查看结果)

I went a slightly different route and made the findKey method an Object protype:

Object.prototype.findKey = function(keyObj) {
    var p, key, val, tRet;
    for (p in keyObj) {
        if (keyObj.hasOwnProperty(p)) {
            key = p;
            val = keyObj[p];
        }
    }

    for (p in this) {
        if (p == key) {
            if (this[p] == val) {
                return this;
            }
        } else if (this[p] instanceof Object) {
            if (this.hasOwnProperty(p)) {
                tRet = this[p].findKey(keyObj);
                if (tRet) { return tRet; }
            }
        }
    }

    return false;
};

Which you would call directly on the data object, passing in the key/value you're looking for:

data.findKey({ id: 3 });

Note that this function allows you to find an object based on any key:

data.findKey({ name: 'Template 0' });

See example → (open console to view result)

顾北清歌寒 2024-11-03 00:58:17

不是最好的最终解决方案。
但可以让你开始了解你正在寻找的东西......

var data = [{id: 0, name: 'Template 0', subComponents:[
        {id: 1, name: 'Template 1', subItems:[
            {id: 2, name: 'Template 2', subComponents:[{id: 3, name: 'Template 3'}], subItems: [{id: 4, name: 'Template 4'}]}
        ]}
    ]}
];


function returnObject(data,key,parent){
    for(var v in data){

        var d = data[v];
        if(d==key){
            return parent[0];
        }
        if(d instanceof Object){
            return returnObject(d,key,data);
        };

    }
}

function returnObjectWrapper(datavar,key){
    return returnObject(datavar,key.id)
}

returnObjectWrapper(data,{id:3})

Not the best of the and final solution.
But can get you a start for what you are looking...

var data = [{id: 0, name: 'Template 0', subComponents:[
        {id: 1, name: 'Template 1', subItems:[
            {id: 2, name: 'Template 2', subComponents:[{id: 3, name: 'Template 3'}], subItems: [{id: 4, name: 'Template 4'}]}
        ]}
    ]}
];


function returnObject(data,key,parent){
    for(var v in data){

        var d = data[v];
        if(d==key){
            return parent[0];
        }
        if(d instanceof Object){
            return returnObject(d,key,data);
        };

    }
}

function returnObjectWrapper(datavar,key){
    return returnObject(datavar,key.id)
}

returnObjectWrapper(data,{id:3})
绻影浮沉 2024-11-03 00:58:17

请参阅下面的我的解决方案或 http://jsfiddle.net/8Y6zq/

var findByKey = function (obj, key) {
var j, key = key || '', obj = obj || {}, keys = key.split("."), 
    sObj = [], ssObj = [], isSelector = !!(keys.length > 0);

    var findKey = function (obj, key) {
        var k;
        for (k in obj) {
            if (k === key) {
                sObj.push(obj[k]);
            } else if (typeof obj[k] == 'object') {
                findKey(obj[k], key);
            }
        }
    };

    if (isSelector) {
        var nKey = keys.shift();
        findKey(obj, nKey);

        while (keys.length > 0) {
            nKey = keys.shift();

            if (sObj.length > 0) {
                ssObj = sObj.slice(0), sObj = [];
                for (j in ssObj) {
                    findKey(ssObj[j], nKey);
                }
            }
        }
    } else {
        findKey(obj, key);
    }

    // return occurrences of key in array
    return (sObj.length === 1) ? sObj.pop() : sObj;
};

var data = [
    {id: 0, name: 'Template 0', subComponents: [
            {id: 1, name: 'Template 1', subItems: [
            {id: 2, name: 'Template 2', subComponents: [
                {id: 3, name: 'Template 3'}
            ], subItems: [
                {id: 4, name: 'Template 4'}
            ]}
        ]}
    ]},
    {subComponents:{
        comp1:'comp1 value',
        comp2:'comp2 value',
    }}
];

alert(JSON.stringify(findByKey(data, 'subComponents')));
alert(JSON.stringify(findByKey(data, 'subComponents.comp1')));
alert(JSON.stringify(findByKey(data, 'subComponents.comp2')));

在此实现中,我们可以使用搜索通过 KEY 或 SELECTOR(例如 "... ..."

Please see my solution below or http://jsfiddle.net/8Y6zq/:

var findByKey = function (obj, key) {
var j, key = key || '', obj = obj || {}, keys = key.split("."), 
    sObj = [], ssObj = [], isSelector = !!(keys.length > 0);

    var findKey = function (obj, key) {
        var k;
        for (k in obj) {
            if (k === key) {
                sObj.push(obj[k]);
            } else if (typeof obj[k] == 'object') {
                findKey(obj[k], key);
            }
        }
    };

    if (isSelector) {
        var nKey = keys.shift();
        findKey(obj, nKey);

        while (keys.length > 0) {
            nKey = keys.shift();

            if (sObj.length > 0) {
                ssObj = sObj.slice(0), sObj = [];
                for (j in ssObj) {
                    findKey(ssObj[j], nKey);
                }
            }
        }
    } else {
        findKey(obj, key);
    }

    // return occurrences of key in array
    return (sObj.length === 1) ? sObj.pop() : sObj;
};

var data = [
    {id: 0, name: 'Template 0', subComponents: [
            {id: 1, name: 'Template 1', subItems: [
            {id: 2, name: 'Template 2', subComponents: [
                {id: 3, name: 'Template 3'}
            ], subItems: [
                {id: 4, name: 'Template 4'}
            ]}
        ]}
    ]},
    {subComponents:{
        comp1:'comp1 value',
        comp2:'comp2 value',
    }}
];

alert(JSON.stringify(findByKey(data, 'subComponents')));
alert(JSON.stringify(findByKey(data, 'subComponents.comp1')));
alert(JSON.stringify(findByKey(data, 'subComponents.comp2')));

In this implementation we can use search by KEY or SELECTOR (eg. "<paren_key>.<child_key_1>.<child_key_2>. ... <child_key_N>")

神经大条 2024-11-03 00:58:17

如果您确实需要搜索树数据并返回所有结果(而不是唯一键),这里是 mVChr 答案的稍微修改版本:

Object.prototype.findKey = function (keyObj) {
var p, key, val, tRet;
var arr = [];

for (p in keyObj) {
    if (keyObj.hasOwnProperty(p)) {
        key = p;
        val = keyObj[p];
    }
}

for (p in this) {
    if (p == key) {
        if (this[p] == val) {
            arr.push(this);
        }
    } else if (this[p] instanceof Object) {
        if (this.hasOwnProperty(p)) {
            tRet = this[p].findKey(keyObj);
            if (tRet) {
                for (var i = 0; i < tRet.length; i++)
                    arr.push(tRet[i]);
            }
        }
    }
}

if (arr.length > 0)
    return arr;
else
    return false;
};

In case you really need a search through your tree data return all results (not a unique key), here is a little modified version of mVChr's answer:

Object.prototype.findKey = function (keyObj) {
var p, key, val, tRet;
var arr = [];

for (p in keyObj) {
    if (keyObj.hasOwnProperty(p)) {
        key = p;
        val = keyObj[p];
    }
}

for (p in this) {
    if (p == key) {
        if (this[p] == val) {
            arr.push(this);
        }
    } else if (this[p] instanceof Object) {
        if (this.hasOwnProperty(p)) {
            tRet = this[p].findKey(keyObj);
            if (tRet) {
                for (var i = 0; i < tRet.length; i++)
                    arr.push(tRet[i]);
            }
        }
    }
}

if (arr.length > 0)
    return arr;
else
    return false;
};
笑饮青盏花 2024-11-03 00:58:17

我们现在使用 object-scan 来执行此类数据处理任务。一旦您了解如何使用它,它就会非常强大。这是您回答问题的方式

// const objectScan = require('object-scan');

const find = (id, input) => objectScan(['**'], {
  abort: true,
  rtn: 'value',
  filterFn: ({ value }) => value.id === id
})(input);

const data = [{ id: 0, name: 'Template 0', subComponents: [{ id: 1, name: 'Template 1', subItems: [{ id: 2, name: 'Template 2', subComponents: [{ id: 3, name: 'Template 3' }], subItems: [{ id: 4, name: 'Template 4' }] }] }] }];

console.log(find(3, data));
// => { id: 3, name: 'Template 3' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

免责声明:我是 object-scan 的作者

We now use object-scan for data processing tasks like this. It's pretty powerful once you wrap your head around how to use it. Here is how you'd answer your questions

// const objectScan = require('object-scan');

const find = (id, input) => objectScan(['**'], {
  abort: true,
  rtn: 'value',
  filterFn: ({ value }) => value.id === id
})(input);

const data = [{ id: 0, name: 'Template 0', subComponents: [{ id: 1, name: 'Template 1', subItems: [{ id: 2, name: 'Template 2', subComponents: [{ id: 3, name: 'Template 3' }], subItems: [{ id: 4, name: 'Template 4' }] }] }] }];

console.log(find(3, data));
// => { id: 3, name: 'Template 3' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文