递归使用数组原型方法

时间:2019-03-18 10:08:15

标签: javascript arrays es6-class

我正在使用无限级结构,类似于此:

    {
  "name": "Group1",
  "type": "group",
  "nodes": [
    {
      "name": "Node1",
      "type": "node",
      "someproperty": "somevalue1"
    },
    {
      "name": "Group2",
      "type": "group",
      "nodes": [
        {
          "name": "Node2",
          "type": "node",
          "someproperty": "somevalue2"
        },
        {
          "name": "Node3",
          "type": "node",
          "someproperty": "somevalue3"
        }
        ]
    }
    ]
}

我们可以在组内有节点,也可以在组内有组。

到目前为止,每次需要做某件事时,我就一直在编写递归函数,但是代码变得非常古怪。

我想知道是否有一种方法可以创建Array.prototype方法的版本,但可以自定义它们以使用递归

例如,通过ID查找任何对象(节点或组),我有一个方法

findNode(target, thisGroup) {

    if (typeof thisGroup == "undefined") {
        thisGroup = this;
    }

    // Am I the element?
    if (thisGroup.id == target) {
        return thisGroup;
    }

    // Look for element in my nodes
    var elementIx = thisGroup.nodes.findIndex(e => e.id == target);
    if (elementIx > 0) {
        // Found the element - return it
        return thisGroup.nodes[elementIx];
    }

    // Not found. Do I contain a group?
    var elementIx = thisGroup.nodes.findIndex(e => e.type == "group");

        if (elementIx > 0) {
            var nestGroup = thisGroup.nodes[elementIx];
            // If so, nest into this group and look again
            return this.findValue(target, nestGroup)
        }

    }

在现实世界中,我需要搜索/嵌套的不只是Id。那么如何创建自己的原型函数,然后可以像这样调用呢?

thisGroup.nodes.findIndexRecursively(e => e.id == target)
thisGroup.nodes.findIndexRecursively(e => e.type=="node" && e.someProp == someValue)

2 个答案:

答案 0 :(得分:2)

我个人不会将其添加到原型中,只需一个简单的函数即可。

这是一个简单的示例,它假设您要递归遍历并检查所有数组。

const data = [{"name":"Group1","type":"group","nodes":[{"name":"Node1","type":"node","someproperty":"somevalue1"},{"name":"Group2","type":"group","nodes":[{"name":"Node2","type":"node","someproperty":"somevalue2"},{"name":"Node3","type":"node","someproperty":"somevalue3"}]}]}];


function rfind(arr, callback) {
  for (const a of arr) {
    const f = callback(a);
    if (f) return a;
    if (!f) {
      for (const o of Object.values(a)) {
        if (Array.isArray(o)) {
          const f2 = rfind(o, callback);
          if (f2) return f2;
        }
      }
    }
  }
}


console.log(rfind(data, f => f.name==="Node1"));
console.log(rfind(data, f => f.name==="Node3"));

答案 1 :(得分:1)

您可以使用递归函数并使用回调进行查找。

function find(node, cb) {
    var result;
    if (cb(node)) return node;
    if (node.nodes) node.nodes.some(o => result = find(o, cb));
    return result;
}

var node = { name: "Group1", type: "group", nodes: [{ name: "Node1", type: "node", someproperty: "somevalue1" }, { name: "Group2", type: "group", nodes: [{ name: "Node2", type: "node", someproperty: "somevalue2" }, { name: "Node3", type: "node", someproperty: "somevalue3" }] }] },
    find1 = find(node, ({ type, someproperty }) => type === 'node' && someproperty === 'somevalue2'),
    find2 = find(node, ({ name, type }) => name === 'Group2' && type === 'group');

console.log(find1);
console.log(find2);
.as-console-wrapper { max-height: 100% !important; top: 0; }