【问题标题】:How to find objects inside nested array of objects using lodash?如何使用 lodash 在嵌套的对象数组中查找对象?
【发布时间】:2019-06-17 10:51:58
【问题描述】:

我有这个数据集

var records = [{
    gc: '2',
    time: 1231232423,
    cards: [{
        cardCode: '12121',
        rssi: 23
      }, {
        cardCode: '12122',
        rssi: 33
      }, {
        cardCode: '12421',
        rssi: 43
      }

    ]
  },
  {
    gc: '3',
    time: 4331232233,
    cards: [{
        cardCode: '6423',
        rssi: 23
      }, {
        cardCode: '12421',
        rssi: 13
      }

    ]
  }, , {
    gc: '4',
    time: 4331232233,
    cards: [{
        cardCode: '8524',
        rssi: 03
      },
      {
        cardCode: '6423',
        rssi: 23
      }, {
        cardCode: '12421',
        rssi: 67
      }
    ]
  }
]

我有一个对象数组(records),每个对象中都有另一个数组(cards)。这意味着如果我将始终在“记录”中存在的对象内拥有cards 数组。所以从一开始我想遍历整个列表records并比较所有对象的卡片数组,然后找到匹配对象的rssi值并将对象(具有最小rssi值)推入另一个新数组.最后以同样的方式,我想要一个数组,其中包含所有具有最小 rssi 值的匹配对象。我正在使用lodash 并尝试过这个

 matchedRecords =   records.forEach(record=>{
 record.cards.forEach(record=>{
  _.filter(records, _.flow(
    _.property('cards'),
     _.partialRight(_.some, { cardCode: record.cardCode })
         ));
      })
   })

我想要的结果是

 [
   {
    gc : 3, 
    cards : [{
     cardCode : '12421',
     rssi : 13
    }]
   }
 ]

注意:卡片数组对象应该在cardCode key的基础上进行比较

【问题讨论】:

  • cardCode: '8524' 的 rssi 应该是 30?如果是 3 应该是最小值。
  • 不,我必须遍历整个 records 数组并在每个卡片数组中找到匹配的卡片并找到具有最小 rssi 的对象。在我上面提到的数据集中,cardCode 等于 12421 的对象存在于records 的所有三个对象中,因此代码应该返回具有最小 rssi 值的对象
  • 你知道只有一张匹配的卡吗?如果不是,gc: 3 在结果中来自哪里?一个 cardCode 的最低 rssi 可能与另一个 cardCode 的最低 rssi 位于不同的记录中。
  • 不,我不知道匹配的卡片是什么,因为卡片数组在records的每个对象中都是动态的
  • 因为代码应该首先比较并获取匹配的记录,所以在我给定的数据集中只有一个对象 cardCode : '12421' 存在。基本上我想根据cardCode匹配记录,你可以看到12421的对象存在于records内的所有三个对象中,通过比较每个对象的rssi,最小rssi为13和cardCode : 12421

标签: javascript lodash


【解决方案1】:

更新

这个版本是基于cmets对问题的长期需求讨论后达成的理解。它不使用 lodash。它已经变得足够复杂,以至于它可能应该分成更小的部分,而 lodash 可能会对此有所帮助。

它不仅包括gc,还包括来自原始记录的time,事实上,它还包括来自那里的任何其他内容。如果您只需要gc,只需从代码中删除...rest

const sharedCards = records => 
  Object.values(
    Object .entries (records .reduce (
      (a, {cards, ...rest}) => cards .reduce (
        (a, {cardCode, rssi}) => ({
          ...a, 
          [cardCode]: [...(a[cardCode] || []), {...rest, rssi}]
        }),
        a,
      ), 
      {}
    ))
    .filter ( ([code, rs]) => rs.length == records.length )
    .reduce((a, [code, rs]) => {
      const {gc, rssi, ...rest} = rs.reduce(
        (r1, r2) => r2.rssi < r1.rssi ?  r2 : r1, 
        {rssi: Infinity}
      )
      return {
        ...a, 
        [gc]: {
          ...(a[gc] || {...rest, gc}), 
          cards: [...((a[gc] || {gc}).cards || []), {cardCode: code, rssi}]
        }
      }
    }, {})  
  )
  
  
const records = [{gc: "2", time: 1231232423, cards: [{cardCode: "12121", rssi: 23}, {cardCode: "12122", rssi:33}, {cardCode: "12421", rssi: 43}]}, {gc: "3", time: 4331232233, cards: [{cardCode: "6423", rssi: 23}, {cardCode: "12421", rssi: 13}]}, {gc: "4", time: 4331232233, cards: [{cardCode: "8524", rssi: 3}, {cardCode: "6423", rssi: 23}, {cardCode: "12421", rssi: 67}]}];

console .log (
  sharedCards (records)
)

// Now we add `{cardCode: "6423", rssi: 7}` to the first record
const records2 = [{gc: "2", time: 1231232423, cards: [{cardCode: "6423", rssi: 7}, {cardCode: "12121", rssi: 23}, {cardCode: "12122", rssi:33}, {cardCode: "12421", rssi: 43}]}, {gc: "3", time: 4331232233, cards: [{cardCode: "6423", rssi: 23}, {cardCode: "12421", rssi: 13}]}, {gc: "4", time: 4331232233, cards: [{cardCode: "8524", rssi: 3}, {cardCode: "6423", rssi: 23}, {cardCode: "12421", rssi: 67}]}];

console .log (
  sharedCards (records2)
)

原答案

这只是部分解决方案,如果我们能解决 cmets 中的讨论,将进行更新。它获取每条记录中出现的所有卡片,并选择具有最低 rssi 的版本。这可能接近要求,也可能不符合要求。

它不使用 lodash。使用 lodash 可能会简化一点,但可能不会很简单。

const sharedCards = records => 
  Object .entries (records .reduce (
    (a, {cards}) => cards .reduce (
      (a, {cardCode, rssi}) => ({...a, [cardCode]: [...(a[cardCode] || []), rssi]}),
      a,
    ), 
    {}
  ))
  .filter ( ([code, rssis]) => rssis.length == records.length )
  .map ( ([code, rssis]) => ({ cardCode: code, rssi: Math .min (...rssis) }) )
    

const records = [{gc: "2", time: 1231232423, cards: [{cardCode: "12121", rssi: 23}, {cardCode: "12122", rssi:33}, {cardCode: "12421", rssi: 43}]}, {gc: "3", time: 4331232233, cards: [{cardCode: "6423", rssi: 23}, {cardCode: "12421", rssi: 13}]}, {gc: "4", time: 4331232233, cards: [{cardCode: "8524", rssi: 3}, {cardCode: "6423", rssi: 23}, {cardCode: "12421", rssi: 67}]}];

console .log (
  sharedCards (records)
)

// Now we add `{cardCode: "6423", rssi: 7}` to the first record
const records2 = [{gc: "2", time: 1231232423, cards: [{cardCode: "6423", rssi: 7}, {cardCode: "12121", rssi: 23}, {cardCode: "12122", rssi:33}, {cardCode: "12421", rssi: 43}]}, {gc: "3", time: 4331232233, cards: [{cardCode: "6423", rssi: 23}, {cardCode: "12421", rssi: 13}]}, {gc: "4", time: 4331232233, cards: [{cardCode: "8524", rssi: 3}, {cardCode: "6423", rssi: 23}, {cardCode: "12421", rssi: 67}]}];

console .log (
  sharedCards (records2)
)

【讨论】:

  • 您的解决方案运行良好,但无法在结果的每个对象中提供 gc。在第一种情况下结果应该是这样的 [{"gc" : "3", cards : [{ "cardCode": "12421", "rssi": 13 }] } 在第二种情况下结果应该是 [{ "gc" :“2”,“卡片”:[{“cardCode”:“6423”,“rssi”:7}]},{“gc”:“3”,“卡片”:[{“cardCode”:“12421” , "rssi": 13 }] } ]
  • @FahadHassanSubzwari:我在获得完整要求之前编写了您看到的版本。我什至在上面的文字中提到了这一点。收到这些要求后,我更新到现在的版本。
【解决方案2】:

使用 Lodash

let records = [{"gc":"2","time":1231232423,"cards":[{"cardCode":"12121","rssi":23},{"cardCode":"12122","rssi":33},{"cardCode":"12421","rssi":43}]},{"gc":"3","time":4331232233,"cards":[{"cardCode":"6423","rssi":23},{"cardCode":"12421","rssi":13}]},{"gc":"4","time":4331232233,"cards":[{"cardCode":"8524","rssi":3},{"cardCode":"6423","rssi":23},{"cardCode":"12421","rssi":67}]}]

let mapped = _.reduce(records, (acc, rec) => {
  _.forEach(rec.cards, (card) => {  
    card = _.assign({}, card, { gc: rec.gc, multiple: false })
    
    if (card.cardCode in acc) {
      let lc = acc[card.cardCode].rssi < card.rssi
      acc[card.cardCode] =  lc ? acc[card.cardCode] : card
      acc[card.cardCode].multiple = lc
    } else {
      acc[card.cardCode] = card;
    }    
  })
  return acc
}, {})

let result = _.reduce(records, (acc, rec) => {
  rec.cards = _.filter(rec.cards, (card) => mapped[card.cardCode].multiple && mapped[card.cardCode].gc === rec.gc )
  rec.cards.length && acc.push(rec)
  return acc
}, []);

console.log(result)
.as-console-wrapper {
  max-height: 100%!important
}
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"&gt;&lt;/script&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-21
    • 2020-01-22
    • 2019-12-31
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多