过滤嵌套数组,并与父对象一起更新数组-JS

时间:2019-11-27 17:45:54

标签: javascript arrays lodash javascript-objects

我有一个对象数组,我需要向该对象以及具有相同值的父数组/对象添加一个键。

以下是我的实现:

const data = [{
    "label": "Grand Parent 1",
    "index": 0,
    "code": "GRAND_PARENT_1",
    "defaultCollapsed": true,
    "items": [{
        "id": 1,
        "items": [{
            "id": 100,
            "label": "Child 1",
            "url": "#CHILD_1",
            "code": "CHILD_1"
          },
          {
            "id": 200,
            "label": "Child 2",
            "url": "#CHILD_2",
            "code": "CHILD_2"
          },
          {
            "id": 300,
            "label": "Child 3",
            "url": "#CHILD_3",
            "code": "CHILD_3"
          },
          {
            "id": 400,
            "label": "Child 4",
            "url": "#CHILD_4",
            "code": "CHILD_4"
          }
        ],
        "defaultCollapsed": false,
        "label": "Parent 1"
      },
      {
        "id": 2,
        "items": [],
        "defaultCollapsed": true,
        "label": "Parent 2"
      },
      {
        "id": 3,
        "items": [],
        "defaultCollapsed": true,
        "label": "Parent 3"
      },
      {
        "id": 4,
        "items": [],
        "defaultCollapsed": true,
        "label": "Parent 4"
      }
    ]
  },
  {
    "label": "Grand Parent 2",
    "index": 1,
    "code": "GRAND_PARENT_2",
    "defaultCollapsed": true,
    "items": []
  },
  {
    "label": "Grand Parent 3",
    "index": 2,
    "code": "GRAND_PARENT_3",
    "defaultCollapsed": true,
    "items": []
  }
]

const filterData = (data, value) => {
  const r = _.filter(data, item => {
    const dataMap = _.map(item.items, subItem => {
        const subItemMap = _.map(subItem.items, subsecItem => {
          if(subsecItem.code === value) {
          return item
          }
        })
    })
  })
  return r;
}

console.log(filterData(data, 'CHILD_1'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

因此,当函数的值为CHILD_1时,我想向子级和父级对象添加名为selected: true的键;

预期输出:

[
  {
    "label": "Grand Parent 1",
    "index": 0,
    "code": "GRAND_PARENT_1",
    "defaultCollapsed": true,
    "selected": true,
    "items": [
      {
        "id": 1,
        "items": [
          {
            "id": 100,
            "label": "Child 1",
            "url": "#CHILD_1",
            "code": "CHILD_1",
            "selected": true
          },
          {
            "id": 200,
            "label": "Child 2",
            "url": "#CHILD_2",
            "code": "CHILD_2"
          },
          {
            "id": 300,
            "label": "Child 3",
            "url": "#CHILD_3",
            "code": "CHILD_3"
          },
          {
            "id": 400,
            "label": "Child 4",
            "url": "#CHILD_4",
            "code": "CHILD_4"
          }
        ],
        "defaultCollapsed": false,
        "label": "Parent 1",
        "selected": true
      },
      {
        "id": 2,
        "items": [],
        "defaultCollapsed": true,
        "label": "Parent 2"
      },
      {
        "id": 3,
        "items": [],
        "defaultCollapsed": true,
        "label": "Parent 3"
      },
      {
        "id": 4,
        "items": [],
        "defaultCollapsed": true,
        "label": "Parent 4"
      }
    ]
  },
  {
    "label": "Grand Parent 2",
    "index": 1,
    "code": "GRAND_PARENT_2",
    "defaultCollapsed": true,
    "items": []
  },
  {
    "label": "Grand Parent 3",
    "index": 2,
    "code": "GRAND_PARENT_3",
    "defaultCollapsed": true,
    "items": []
  }
]

请咨询。我被困在尝试根据值过滤数据。

2 个答案:

答案 0 :(得分:1)

此解决方案效率更高,因为一旦找到给定的孩子,它将立即停止。 forEach()不允许您这样做。我还发现阅读起来更加清晰。

function select(items, value) {
  if (!Array.isArray(items)) {
    return false;
  }

  for (const item of items) {
    if (item.code === value || select(item.items, key, value)) {
      item.selected = true;
      return true;
    }
  }

  return false;
}

select(data, "CHILD_1");

select()如果找到孩子,则返回true,否则返回false。

如果您需要取消选择先前选择的内容:

function reset(items) {
  if (!Array.isArray(items)) {
    return;
  }

  for (const item of items) {
    if (item.selected) {
      reset(item.items);
      delete item.selected;
      break;
    }
  }
}

reset(data);

这种方法与选择一样聪明,因为一旦找到所选元素,它就会停止。

要同时执行这两项:

function resetAndSelect(data, value) {
  reset(data);
  select(data, value);
}

答案 1 :(得分:0)

您可以采用返回truefalse的函数,具体取决于要使用其他属性更新对象的所需键/值。

这种方法适用于任意深度的数据。

function update(array, key, value, object) {
    var found = false;
    array.forEach(o => {
        if (o[key] === value || update(o.items || [], key, value, object)) {
            found = true;
            Object.assign(o, object);
        }
    });
    return found;
}

var data = [{ label: "Grand Parent 1", index: 0, code: "GRAND_PARENT_1", defaultCollapsed: true, items: [{ id: 1, items: [{ id: 100, label: "Child 1", url: "#CHILD_1", code: "CHILD_1" }, { id: 200, label: "Child 2", url: "#CHILD_2", code: "CHILD_2" }, { id: 300, label: "Child 3", url: "#CHILD_3", code: "CHILD_3" }, { id: 400, label: "Child 4", url: "#CHILD_4", code: "CHILD_4" }], defaultCollapsed: false, label: "Parent 1" }, { id: 2, items: [], defaultCollapsed: true, label: "Parent 2" }, { id: 3, items: [], defaultCollapsed: true, label: "Parent 3" }, { id: 4, items: [], defaultCollapsed: true, label: "Parent 4" }] }, { label: "Grand Parent 2", index: 1, code: "GRAND_PARENT_2", defaultCollapsed: true, items: [] }, { label: "Grand Parent 3", index: 2, code: "GRAND_PARENT_3", defaultCollapsed: true, items: [] }];

update(data, 'code', 'CHILD_1', { selected: true });

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

如果您希望将所有未找到的项目设置为false,则可以采用深度优先的方法来访问所有元素。

function update(array, value) {
    var found = false;
    array.forEach(o => {
        o.selected = update(o.items || [], value) || o.code === value;
        found = found || o.selected;
    });
    return found;
}

var data = [{ label: "Grand Parent 1", index: 0, code: "GRAND_PARENT_1", defaultCollapsed: true, items: [{ id: 1, items: [{ id: 100, label: "Child 1", url: "#CHILD_1", code: "CHILD_1" }, { id: 200, label: "Child 2", url: "#CHILD_2", code: "CHILD_2" }, { id: 300, label: "Child 3", url: "#CHILD_3", code: "CHILD_3" }, { id: 400, label: "Child 4", url: "#CHILD_4", code: "CHILD_4" }], defaultCollapsed: false, label: "Parent 1" }, { id: 2, items: [], defaultCollapsed: true, label: "Parent 2" }, { id: 3, items: [], defaultCollapsed: true, label: "Parent 3" }, { id: 4, items: [], defaultCollapsed: true, label: "Parent 4" }] }, { label: "Grand Parent 2", index: 1, code: "GRAND_PARENT_2", defaultCollapsed: true, items: [] }, { label: "Grand Parent 3", index: 2, code: "GRAND_PARENT_3", defaultCollapsed: true, items: [] }];

update(data, 'CHILD_1');

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

相关问题