将对象推入递归中的数组

发布于 2025-01-21 08:02:23 字数 1097 浏览 0 评论 0原文

我有两个数组: 第一arr-具有多级结构。
第二ARR-带有对象的线性数组。

在我的更新功能中,我迭代了第一个数组的儿童,如果条件为真,我将对象推入属性。

在生产中 - 我有arr2.length -150000对象和arr1.length-多个深度级别。

如何优化我的功能以更快地使用大数据循环?现在,我等待大约5分钟的迭代。

var arr1 = [{
    "item_id": 2,
    "item_name": "test",
    "children": [{
        "item_id": 39646,
        "item_name": "test1",
        "children": [{
            "item_id": 35648,
            "item_name": "test2",
            "children": [{
                "item_id": 35771,
                "item_name": "test3",
                "children": [],
                "attributes": []
            }],
        }]
    }]
}]


var arr2 = [
    {
        "item_id": 35771,
        "attr_value": "test",
    }, {
        "item_id": 35771,
        "attr_value": "test1",
    }
]


const update = (array, id, object) => array.forEach(o => o.item_id === id ?
    o.attributes.push(object) : update(o.children, id, object)
);

for (let item of arr2) {
   update(arr1, item.item_id, item);
}

console.log(arr1)

I have two arrays:
first arr - has multiple level structure.
second arr - linear array with objects.

In my update function I iterate throw my first array childrens and if condition true, I push objects into attributes.

In production - I have arr2.length - 150000 objects and arr1.length - multiple deep levels.

How I can optimize my function to loop more quickly with a big data? Now, I wait about 5 minutes on iteration.

var arr1 = [{
    "item_id": 2,
    "item_name": "test",
    "children": [{
        "item_id": 39646,
        "item_name": "test1",
        "children": [{
            "item_id": 35648,
            "item_name": "test2",
            "children": [{
                "item_id": 35771,
                "item_name": "test3",
                "children": [],
                "attributes": []
            }],
        }]
    }]
}]


var arr2 = [
    {
        "item_id": 35771,
        "attr_value": "test",
    }, {
        "item_id": 35771,
        "attr_value": "test1",
    }
]


const update = (array, id, object) => array.forEach(o => o.item_id === id ?
    o.attributes.push(object) : update(o.children, id, object)
);

for (let item of arr2) {
   update(arr1, item.item_id, item);
}

console.log(arr1)

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

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

发布评论

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

评论(2

神回复 2025-01-28 08:02:23

在将您的第二个数组转换为此格式之后,我们可以走一次:

{
  35771: ['test', 'test1']
  // ...
}

对于树的每个节点,只需添加列表中的属性即可。这是一个实现:

const updateForest = (atts) => (forest) =>
  forest .map (({item_id, children = [], ...rest}) => ({
    item_id,
    ...rest,
    children: updateForest (atts) (children),
    ...(atts [item_id] ? {attributes: atts [item_id]} : {})
  }))

const addAttributes = (forest, atts) => 
  updateForest (atts .reduce (
    (a, {item_id, attr_value}) => ((a [item_id] = a [item_id] || []), (a [item_id] .push (attr_value)), a), 
    {}
  )) (forest)

const arr1 = [{item_id: 2, item_name: "test", children: [{item_id: 39646, item_name: "test1", children: [{item_id: 35648, item_name: "test2", children: [{item_id: 35771, item_name: "test3", children: [], attributes: []}]}]}]}]
const arr2 = [{item_id: 35771, attr_value: "test"}, {item_id: 35771, attr_value: "test1"}]


console .log (addAttributes (arr1, arr2))
.as-console-wrapper {max-height: 100% !important; top: 0}

updateForest接收到所述重新格式化的属性,并返回一个函数,该函数将您的森林结构(不是树)(因为它不一定是单一根深蒂固的)并访问其节点,并在其上添加属性,并在其上添加属性。儿童名单。

我们的公共功能是addAttributes。这使用降低在您的属性上进行该格式转换,然后将其传递给Updateforest

重要的是,这并不是要突变您的原始结构,而是创建新结构。我发现这是编码时的重要目标。但是,如果您的数据如此之大,以至于我们无法在内存中安装两个副本,那么我们必须跳过此方法。

We can walk the tree once, after converting your second array into this format:

{
  35771: ['test', 'test1']
  // ...
}

and for each node of the tree just adding the attributes from this list if they exist. Here's an implementation:

const updateForest = (atts) => (forest) =>
  forest .map (({item_id, children = [], ...rest}) => ({
    item_id,
    ...rest,
    children: updateForest (atts) (children),
    ...(atts [item_id] ? {attributes: atts [item_id]} : {})
  }))

const addAttributes = (forest, atts) => 
  updateForest (atts .reduce (
    (a, {item_id, attr_value}) => ((a [item_id] = a [item_id] || []), (a [item_id] .push (attr_value)), a), 
    {}
  )) (forest)

const arr1 = [{item_id: 2, item_name: "test", children: [{item_id: 39646, item_name: "test1", children: [{item_id: 35648, item_name: "test2", children: [{item_id: 35771, item_name: "test3", children: [], attributes: []}]}]}]}]
const arr2 = [{item_id: 35771, attr_value: "test"}, {item_id: 35771, attr_value: "test1"}]


console .log (addAttributes (arr1, arr2))
.as-console-wrapper {max-height: 100% !important; top: 0}

updateForest receives the attributes reformatted as described and returns a function which takes your forest structure (it's not a tree, because it's not necessarily singly-rooted) and visits its nodes, adding attributes if they exist, recurring on the list of children.

Our public function is addAttributes. This uses reduce to do that format conversion on your attributes, passing it and then the forest to updateForest.

It's important to not that this does not mutate your original structures, but creates new ones. I find this an important goal when coding. But if your data is so large that we can't fit two copies in memory, then we'd have to skip this approach.

紫竹語嫣☆ 2025-01-28 08:02:23

一种方法是创建一张地图,该地图告诉您在ARR1中找到该项目的确切位置。
类似的东西:

const mappedArr1 = {
    2: {}, // Reference to item 2
    39646: {}, // Reference to item 39646
    35648: {}, // Reference to item 35648
    35771: {}, // Reference to item 35771
}

当您更新时要做:

const item = mappedArr1[id];
item.attributes.push(object);

创建地图可能会使用类似的内容:

const map = array => {
  const data = {};
  const doMap = array => array.forEach(i => {
    data[i.item_id] = i;
    if (i.children && i.children.length > 0) {
      doMap(i.children);
    }
  });
  doMap(array);
    return data;
}

const mappeArr1 = map(arr1);

这是完整的代码:

var arr1 = [{
    "item_id": 2,
    "item_name": "test",
    "children": [{
        "item_id": 39646,
        "item_name": "test1",
        "children": [{
            "item_id": 35648,
            "item_name": "test2",
            "children": [{
                "item_id": 35771,
                "item_name": "test3",
                "children": [],
                "attributes": []
            }],
        }]
    }]
}]


var arr2 = [
    {
        "item_id": 35771,
        "attr_value": "test",
    }, {
        "item_id": 35771,
        "attr_value": "test1",
    }
]

const map = array => {
  const data = {};
  const doMap = array => array.forEach(i => {
    data[i.item_id] = i;
    if (i.children && i.children.length > 0) {
      doMap(i.children);
    }
  });
  doMap(array);
  return data;
}

const mappedArr1 = map(arr1);

for (let i of arr2) {
   const item = mappedArr1[i.item_id];
   item.attributes.push(i.attr_value);
}

console.log(arr1)

使用jsbench测试多个实现的性能,您需要一个更大的数据示例: https://jsbench.me

One way would be to create a map that tells you exactly where to find the item in arr1.
Something like this:

const mappedArr1 = {
    2: {}, // Reference to item 2
    39646: {}, // Reference to item 39646
    35648: {}, // Reference to item 35648
    35771: {}, // Reference to item 35771
}

And when you update just do:

const item = mappedArr1[id];
item.attributes.push(object);

To create the map maybe use something like this:

const map = array => {
  const data = {};
  const doMap = array => array.forEach(i => {
    data[i.item_id] = i;
    if (i.children && i.children.length > 0) {
      doMap(i.children);
    }
  });
  doMap(array);
    return data;
}

const mappeArr1 = map(arr1);

Here is the full code:

var arr1 = [{
    "item_id": 2,
    "item_name": "test",
    "children": [{
        "item_id": 39646,
        "item_name": "test1",
        "children": [{
            "item_id": 35648,
            "item_name": "test2",
            "children": [{
                "item_id": 35771,
                "item_name": "test3",
                "children": [],
                "attributes": []
            }],
        }]
    }]
}]


var arr2 = [
    {
        "item_id": 35771,
        "attr_value": "test",
    }, {
        "item_id": 35771,
        "attr_value": "test1",
    }
]

const map = array => {
  const data = {};
  const doMap = array => array.forEach(i => {
    data[i.item_id] = i;
    if (i.children && i.children.length > 0) {
      doMap(i.children);
    }
  });
  doMap(array);
  return data;
}

const mappedArr1 = map(arr1);

for (let i of arr2) {
   const item = mappedArr1[i.item_id];
   item.attributes.push(i.attr_value);
}

console.log(arr1)

Use JSBench to test the performance of multiple implementations, you will need a bigger data sample: https://jsbench.me

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