如何使用lodash在嵌套的对象数组中查找对象?

时间:2019-06-17 10:51:58

标签: javascript lodash

我有此数据集

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的重低音上进行比较

2 个答案:

答案 0 :(得分:1)

已更新

此版本基于对问题的评论中的长期需求讨论之后达成的理解。它不使用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)
)

原始答案

这只是部分解决方案,如果我们可以解决评论中的讨论,请予以更新。它获取出现在每条记录中的所有卡,并选择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)
)

答案 1 :(得分:0)

和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
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>