【问题标题】:Find property key name from nested array of objects从嵌套的对象数组中查找属性键名
【发布时间】:2019-12-19 19:18:04
【问题描述】:

我有一个对象数组,我需要获取“选定”为真的“代码”值。在任何情况下,selected 仅对一个项目为 true。我已经完成了一个实现,有什么方法可以改进它吗?

const data = [
  {
    "id": "1",
    "code": "A",
    "selected": true,
    "defaultCollapsed": false,
    "label": "A",
    "items": [
      {
        "id": "A1",
        "code": "A1",
        "label": "A-1 PP",
        "selected": true,
        "defaultCollapsed": false,
        "url": "#A1"
      },
      {
        "id": "A2",
        "code": "A2",
        "label": "A-2 ST",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#A2"
      },
      {
        "id": "A3",
        "code": "A3",
        "label": "A-3 SR",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#A3"
      },
      {
        "id": "A4",
        "code": "A4",
        "label": "A-4 BLS",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#A4"
      },
      {
        "id": "A5",
        "code": "A5",
        "label": "A-5 BIFO",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#A5"
      },
      {
        "id": "A6",
        "code": "A6",
        "label": "A-6 VA",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#A6"
      }
    ]
  },
  {
    "id": "2",
    "code": "B",
    "selected": false,
    "defaultCollapsed": true,
    "label": "B. ECQG",
    "items": [
      {
        "id": "B1",
        "code": "B1",
        "label": "B-1 VR",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#B1"
      }
    ]
  },
  {
    "id": "3",
    "code": "C",
    "selected": false,
    "defaultCollapsed": true,
    "label": "C. CRR",
    "items": [
      {
        "id": "C1",
        "code": "C1",
        "label": "C-1 RSR",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#C1"
      },
      {
        "id": "C2",
        "code": "C2",
        "label": "C-2 Other",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#C2"
      }
    ]
  }
]

console.log(_.find(_.find(data, item => _.find(item.items, item1 => item1.selected)).items, item3 => item3.selected).code)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

上述示例的预期结束输出为“A1”。 请指教。

【问题讨论】:

  • 请添加想要的结果。
  • 添加了尼娜.....
  • 您需要 lodash 解决方案吗?原生 JavaScript .find() 可能比嵌套的 lodash _.find() 方法更具可读性。 (尽管,可能有更好的替代 lodash 方法。)
  • @TylerRoper 没关系。我使用了 lodash,我们在代码中设置了 eslint-plugin-lodash

标签: javascript arrays lodash


【解决方案1】:

通过Array.flatMap()将item扁平化为单个数组,然后使用Array.find()得到选中的item:

const data = [{"id":"1","code":"A","selected":true,"defaultCollapsed":false,"label":"A","items":[{"id":"A1","code":"A1","label":"A-1 PP","selected":true,"defaultCollapsed":false,"url":"#A1"},{"id":"A2","code":"A2","label":"A-2 ST","selected":false,"defaultCollapsed":true,"url":"#A2"},{"id":"A3","code":"A3","label":"A-3 SR","selected":false,"defaultCollapsed":true,"url":"#A3"},{"id":"A4","code":"A4","label":"A-4 BLS","selected":false,"defaultCollapsed":true,"url":"#A4"},{"id":"A5","code":"A5","label":"A-5 BIFO","selected":false,"defaultCollapsed":true,"url":"#A5"},{"id":"A6","code":"A6","label":"A-6 VA","selected":false,"defaultCollapsed":true,"url":"#A6"}]},{"id":"2","code":"B","selected":false,"defaultCollapsed":true,"label":"B. ECQG","items":[{"id":"B1","code":"B1","label":"B-1 VR","selected":false,"defaultCollapsed":true,"url":"#B1"}]},{"id":"3","code":"C","selected":false,"defaultCollapsed":true,"label":"C. CRR","items":[{"id":"C1","code":"C1","label":"C-1 RSR","selected":false,"defaultCollapsed":true,"url":"#C1"},{"id":"C2","code":"C2","label":"C-2 Other","selected":false,"defaultCollapsed":true,"url":"#C2"}]}]

const result = data
  .flatMap(o => o.items) // flatten items to a single array
  .find(o => o.selected === true) // find the item

console.log(result)

使用相同原理的lodash版本:

const data = [{"id":"1","code":"A","selected":true,"defaultCollapsed":false,"label":"A","items":[{"id":"A1","code":"A1","label":"A-1 PP","selected":true,"defaultCollapsed":false,"url":"#A1"},{"id":"A2","code":"A2","label":"A-2 ST","selected":false,"defaultCollapsed":true,"url":"#A2"},{"id":"A3","code":"A3","label":"A-3 SR","selected":false,"defaultCollapsed":true,"url":"#A3"},{"id":"A4","code":"A4","label":"A-4 BLS","selected":false,"defaultCollapsed":true,"url":"#A4"},{"id":"A5","code":"A5","label":"A-5 BIFO","selected":false,"defaultCollapsed":true,"url":"#A5"},{"id":"A6","code":"A6","label":"A-6 VA","selected":false,"defaultCollapsed":true,"url":"#A6"}]},{"id":"2","code":"B","selected":false,"defaultCollapsed":true,"label":"B. ECQG","items":[{"id":"B1","code":"B1","label":"B-1 VR","selected":false,"defaultCollapsed":true,"url":"#B1"}]},{"id":"3","code":"C","selected":false,"defaultCollapsed":true,"label":"C. CRR","items":[{"id":"C1","code":"C1","label":"C-1 RSR","selected":false,"defaultCollapsed":true,"url":"#C1"},{"id":"C2","code":"C2","label":"C-2 Other","selected":false,"defaultCollapsed":true,"url":"#C2"}]}]

const result = _.find(_.flatMap(data, 'items'), 'selected')

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

【讨论】:

  • Flatmap 循环数据数组中的所有项目,这可能不是必需的。这是一个优雅的解决方案,而不是最有效的解决方案。
【解决方案2】:

您可以通过两个嵌套的reduce() 函数来实现这一点:

const data = [{"id":"1","code":"A","selected":true,"defaultCollapsed":false,"label":"A","items":[{"id":"A1","code":"A1","label":"A-1 PP","selected":true,"defaultCollapsed":false,"url":"#A1"},{"id":"A2","code":"A2","label":"A-2 ST","selected":false,"defaultCollapsed":true,"url":"#A2"},{"id":"A3","code":"A3","label":"A-3 SR","selected":false,"defaultCollapsed":true,"url":"#A3"},{"id":"A4","code":"A4","label":"A-4 BLS","selected":false,"defaultCollapsed":true,"url":"#A4"},{"id":"A5","code":"A5","label":"A-5 BIFO","selected":false,"defaultCollapsed":true,"url":"#A5"},{"id":"A6","code":"A6","label":"A-6 VA","selected":false,"defaultCollapsed":true,"url":"#A6"}]},{"id":"2","code":"B","selected":false,"defaultCollapsed":true,"label":"B. ECQG","items":[{"id":"B1","code":"B1","label":"B-1 VR","selected":false,"defaultCollapsed":true,"url":"#B1"}]},{"id":"3","code":"C","selected":false,"defaultCollapsed":true,"label":"C. CRR","items":[{"id":"C1","code":"C1","label":"C-1 RSR","selected":false,"defaultCollapsed":true,"url":"#C1"},{"id":"C2","code":"C2","label":"C-2 Other","selected":false,"defaultCollapsed":true,"url":"#C2"}]}]


const res = data.reduce((acc1,cur1) => {
    if(cur1.selected){
        return cur1.items.reduce((acc2,cur2) => {
            return cur2.selected ? acc2.concat(cur2.id) : acc2
        },[])
    }else{
        return acc1
    }
},[])

console.log(res)

【讨论】:

  • 循环所有项目,无论是否找到。
【解决方案3】:

没有太多需要改进的地方。 Find 将在第一个值为 true 时停止。

唯一的改进空间可能是使其更具可读性并且只使用原生 JavaScript。

const data = [
  {
    "id": "1",
    "code": "A",
    "selected": true,
    "defaultCollapsed": false,
    "label": "A",
    "items": [
      {
        "id": "A1",
        "code": "A1",
        "label": "A-1 PP",
        "selected": true,
        "defaultCollapsed": false,
        "url": "#A1"
      },
      {
        "id": "A2",
        "code": "A2",
        "label": "A-2 ST",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#A2"
      },
      {
        "id": "A3",
        "code": "A3",
        "label": "A-3 SR",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#A3"
      },
      {
        "id": "A4",
        "code": "A4",
        "label": "A-4 BLS",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#A4"
      },
      {
        "id": "A5",
        "code": "A5",
        "label": "A-5 BIFO",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#A5"
      },
      {
        "id": "A6",
        "code": "A6",
        "label": "A-6 VA",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#A6"
      }
    ]
  },
  {
    "id": "2",
    "code": "B",
    "selected": false,
    "defaultCollapsed": true,
    "label": "B. ECQG",
    "items": [
      {
        "id": "B1",
        "code": "B1",
        "label": "B-1 VR",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#B1"
      }
    ]
  },
  {
    "id": "3",
    "code": "C",
    "selected": false,
    "defaultCollapsed": true,
    "label": "C. CRR",
    "items": [
      {
        "id": "C1",
        "code": "C1",
        "label": "C-1 RSR",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#C1"
      },
      {
        "id": "C2",
        "code": "C2",
        "label": "C-2 Other",
        "selected": false,
        "defaultCollapsed": true,
        "url": "#C2"
      }
    ]
  }
]

console.log(_.find(_.find(data, item => _.find(item.items, item1 => item1.selected)).items, item3 => item3.selected).code)

// More readable than above
// Find is the best option as it stops once the condition is true
function findSelected(dataToSearch) {
   let childIndex = -1;
   const parentIndex = dataToSearch.findIndex((codedData) => {
       return childIndex = codedData.items.findIndex(anotherCodedData => anotherCodedData.selected)
   });
   if (parentIndex != -1 && childIndex =! -1) { return dataToSearch[parentIndex].items[childIndex] }
   return null
}
const foundData = findSelected(data);
if (foundData) { console.log(foundData.code) }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

【讨论】:

  • Array.findIndex() 在未找到任何项目时返回 -1。另外 0 是一个合法的索引。这意味着parentIndex && childIndex 将在未找到该项目时给出误报,这将导致返回语句出错。另一方面,如果父级或子级的索引为 0,则返回值为 null。如果您想手动迭代项目并在找到项目时返回项目,请使用两个 for...of 循环。
  • 你是对的! -1 在 JavaScript 中甚至是真实的。纠正我的错误
猜你喜欢
  • 1970-01-01
  • 2017-12-24
  • 2023-03-26
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 2013-10-11
  • 1970-01-01
  • 2021-10-29
相关资源
最近更新 更多