首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用JavaScript查找指向给定值的完整对象路径

使用JavaScript查找指向给定值的完整对象路径
EN

Stack Overflow用户
提问于 2018-11-29 16:17:19
回答 4查看 8K关注 0票数 3

我有一个包含项目(只有name属性)和组(具有children属性,它们可能包含项或其他组)的对象数组,我需要获得一个通向needle值的完整路径,所以在本例中它是myObj[2]["children"][0]["children"][1]["children"][0],而且我仅限于相当老的JS版本ECMA262(我在Photoshop中使用它)。

代码语言:javascript
复制
var myObj = [
{
    "name": "group1",
    "children": [
    {
        "name": "group2",
        "children": [
        {
            "name": "item0"
        }]
    }]
},
{
    "name": "item1"
},
{
    "name": "needleGroup",
    "children": [
    {
        "name": "needleNestedGroup",
        "children": [
        {
            "name": "item3"
        },
        {
            "name": "needleNestedDeeperGroup",
            "children": [
            {
                "name": "needle"
            }]
        }]
    }]
}];

我的第一个想法是将对象转换为数组或数组,这样处理起来就更容易了,所以我的对象变成了

代码语言:javascript
复制
[
    [
        [
            "item0"
        ]
    ],
    "item1", 
    [
        [
            "item3", 
            [
                "needle"
            ]
        ]
    ]
];

但是..。就这样。我找不到只找到我需要的索引的热度。你能指出正确的方向吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-11-29 17:17:12

使用递归函数查找所需的项。一旦函数找到它,它将返回一个数组。递归的每一步后退都将unshift该步骤的对象键:

代码语言:javascript
复制
function find(obj, item) {
    for(var key in obj) {                                   // for each key in obj (obj is either an object or an array)
        if(obj[key] && typeof obj[key] === "object") {      // if the current property (value of obj[key]) is also an object/array
            var result = find(obj[key], item);              // try finding item in that object
            if(result) {                                    // if we find it
                result.unshift(key);                        // we shift the current key to the path array (result will be an array of keys)
                return result;                              // and we return it to our caller
            }
        } else if(obj[key] === item) {                      // otherwise (if obj[key] is not an object or array) we check if it is the item we're looking for
            return [key];                                   // if it is then we return the path array (this is where the path array get constructed)
        }
    }
}

此函数的输出将是指向item的键数组。您可以轻松地将其转换为问题中的格式:

代码语言:javascript
复制
function findFormatted(obj, item) {
    var path = find(obj, item);                             // first let's get the path array to item (if it exists)
    if(path == null) {                                      // if it doesn't exist
        return "";                                          // return something to signal its inexistance
    }
    return 'myObj["' + path.join('"]["') + '"]';            // otherwise format the path array into a string and return it
}

示例:

代码语言:javascript
复制
function find(obj, item) {
    for(var key in obj) {
        if(obj[key] && typeof obj[key] === "object") {
            var result = find(obj[key], item);
            if(result) {
                result.unshift(key);
                return result;
            }
        } else if(obj[key] === item) {
            return [key];
        }
    }
}

function findFormatted(obj, item) {
    var path = find(obj, item);
    if(path == null) {
        return "";
    }
    return 'myObj["' + path.join('"]["') + '"]';
}

var myObj = [{"name":"group1","children":[{"name":"group2","children":[{"name":"item0"}]}]},{"name":"item1"},{"name":"needleGroup","children":[{"name":"needleNestedGroup","children":[{"name":"item3"},{"name":"needleNestedDeeperGroup","children":[{"name":"needle"}]}]}]}];

console.log("find(myObj, \"needle\"):          " + JSON.stringify(find(myObj, "needle")));
console.log("findFormatted(myObj, \"needle\"): " + findFormatted(myObj, "needle"));

注意:数组的索引也被格式化为字符串,但这不是问题,因为someArray["2"]等同于someArray[2]

票数 7
EN

Stack Overflow用户

发布于 2019-11-06 11:56:46

我创造了一些你可能会用到的东西。下面的代码返回您要查找的键、值、对象的路径数组。

请参阅片段和示例,看看您能做些什么。

要使其工作,您必须传递您想要在元素和元素中找到的键和/或值,这是一个Array或对象。

它是用较新的JS标准编写的,但是将其编译成旧标准应该不会有问题。

代码语言:javascript
复制
function findKeyValuePairsPath(keyToFind, valueToFind, element) {
  if ((keyToFind === undefined || keyToFind === null) &&
    (valueToFind === undefined || valueToFind === null)) {
    console.error('You have to pass key and/or value to find in element!');
    return [];
  }

  const parsedElement = JSON.parse(JSON.stringify(element));
  const paths = [];

  if (this.isObject(parsedElement) || this.isArray(parsedElement)) {
    checkObjOrArr(parsedElement, keyToFind, valueToFind, 'baseElement', paths);
  } else {
    console.error('Element must be an Object or Array type!', parsedElement);
  }

  console.warn('Main element', parsedElement);
  return paths;
}

function isObject(elem) {
  return elem && typeof elem === 'object' && elem.constructor === Object;
}

function isArray(elem) {
  return Array.isArray(elem);
}

function checkObj(obj, keyToFind, valueToFind, path, paths) {
  Object.entries(obj).forEach(([key, value]) => {
    if (!keyToFind && valueToFind === value) {
      // we are looking for value only
      paths.push(`${path}.${key}`);
    } else if (!valueToFind && keyToFind === key) {
      // we are looking for key only
      paths.push(path);
    } else if (key === keyToFind && value === valueToFind) {
      // we ale looking for key: value pair
      paths.push(path);
    }

    checkObjOrArr(value, keyToFind, valueToFind, `${path}.${key}`, paths);
  });
}

function checkArr(array, keyToFind, valueToFind, path, paths) {
  array.forEach((elem, i) => {
    if (!keyToFind && valueToFind === elem) {
      // we are looking for value only
      paths.push(`${path}[${i}]`);
    }
    checkObjOrArr(elem, keyToFind, valueToFind, `${path}[${i}]`, paths);
  });
}

function checkObjOrArr(elem, keyToFind, valueToFind, path, paths) {
  if (this.isObject(elem)) {
    checkObj(elem, keyToFind, valueToFind, path, paths);
  } else if (this.isArray(elem)) {
    checkArr(elem, keyToFind, valueToFind, path, paths);
  }
}

const example = [
  {
    exampleArr: ['lol', 'test', 'rotfl', 'yolo'],
    key: 'lol',
  },
  {
    exampleArr: [],
    key: 'lol',
  },
  {
    anotherKey: {
      nestedKey: {
        anotherArr: ['yolo'],
      },
      anotherNestedKey: 'yolo',
    },
    emptyKey: null,
    key: 'yolo',
  },
];

console.log(findKeyValuePairsPath('key', 'lol', example)); // ["baseElement[0]", "baseElement[1]"]
console.log(findKeyValuePairsPath(null, 'yolo', example)); // ["baseElement[0].exampleArr[3]", "baseElement[2].anotherKey.nestedKey.anotherArr[0]", "baseElement[2].anotherKey.anotherNestedKey", "baseElement[2].key"]
console.log(findKeyValuePairsPath('anotherNestedKey', null, example)); //["baseElement[2].anotherKey"]

票数 1
EN

Stack Overflow用户

发布于 2022-01-21 13:38:17

我解决了这个问题,并抓住机会创建了查找对象路径,这解决了这个问题:通过键、值或键/值组合在对象中查找路径。

NPM:查找对象路径

Github:getPaths

示例对象:

代码语言:javascript
复制
{
          "company": {
            "name": "ACME INC",
            "address": "1st Street, Toontown, TT",
            "founded": "December 31st 1969",
            "hasStocks": true,
            "numberOfEmployees": 2,
            "numberOfActors": 3
          },
          "employees": [
            {
              "employeeNumber": 1,
              "name": "Hugo Boss",
              "age": 65,
              "isCEO": true
            },
            {
              "employeeNumber": 2,
              "name": "Herbert Assistant",
              "age": 32,
              "isCEO": false
            }
          ],
          "actors": [
            {
              "actorId": 1,
              "name": "Bugs Bunny",
              "retired": false,
              "playedIn": [
                {
                  "movie": "Who Framed Roger Rabbit",
                  "started": 1988
                },
                {
                  "movie": "Space Jam",
                  "started": 1996
                },
                {
                  "movie": "Looney Tunes: Back in Action",
                  "started": 2003
                }
              ]
            },
            {
              "actorId": 2,
              "name": "Pepé le Pew",
              "retired": true,
              "playedIn": [
                {
                  "movie": "For Scent-imental Reasons",
                  "started": 1949
                }
              ]
            },
            {
              "actorId": 3,
              "name": "Marvin the Martian",
              "retired": true,
              "playedIn": [
                {
                  "movie": "Marvin the Martian in the Third Dimension",
                  "started": 1996
                },
                {
                  "movie": "Duck Dodgers and the Return of the 24½th Century",
                  "started": 1980
                },
                {
                  "movie": "Hare-Way to the Stars",
                  "started": 1958
                }
              ]
            },
            {
              "actorId": 4,
              "name": "Yosemite Sam",
              "retired": false,
              "playedIn": [
                {
                  "movie": "Who Framed Roger Rabbit",
                  "started": 1988
                },
                {
                  "movie": "Space Jam",
                  "started": 1996
                },
                {
                  "movie": "Looney Tunes: Back in Action",
                  "started": 2003
                }
              ]
            }
          ],
          "distributionChannels": [
            "Celluloyd",
            [
              "VHS",
              "Betamax",
              "DVD",
              "Blueray"
            ],
            [
              "channel",
              12,
              true
            ]
          ]
    }

因此,基本用法可以是:

代码语言:javascript
复制
import { findObjectPaths } from 'findObjectPaths';

class TestMe {

    static async main() {
        let acmeInc = {};
        rawFileContent = fs.readFileSync(p.resolve(__dirname, 'acmeInc.json'), 'utf-8');
        acmeInc = JSON.parse(rawFileContent);

        let path = findObjectPaths(acmeInc, {key: 'founded'});
        // company.founded
        path = findObjectPaths(acmeInc, {value: 'December 31st 1969'});
        // company.founded

        const allPaths: string[] = findObjectPaths(acmeInc, {key: 'actorId'}) as string[];
        /* [ 'actors[0].actorId',
             'actors[1].actorId',
             'actors[2].actorId',
             'actors[3].actorId' ]
         */

        const ceoPath = findObjectPaths(acmeInc, {key: 'isCEO', value: true});
         // employees[0].isCEO
    }
}

TestMe.main();

请参阅这里的完整文档:https://github.com/maugenst/getPaths#readme

BR

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53543303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档