0

I have this data set

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
      }
    ]
  }
]

I have an array(records) of objects and in each object there is an another array(cards). This means if i will always have cards array inside an object present in 'records'. So from very first i want to iterate over whole list records and compare the cards array of all objects with each other and then find the matched object's rssi value and push the object(that have minimum rssi value ) into another new array. In the same way at the end i want the array in which i have all the matching objects which have minimum rssi value. I am using lodash and have tried this

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

My desired result would be

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

Note : cards array object should be compare on the bassis of cardCode key

11
  • The cardCode: '8524' should have an rssi of 30? If it's 3 it should be the minimum. Commented Jun 17, 2019 at 11:12
  • No i have to iterate through whole records array and find matching cards inside each cards array and find the object which has minimum rssi. In my above mentioned data set the object which have cardCode equal to 12421 is present in all three objects of records so code should be return the object which has minimum rssi value Commented Jun 17, 2019 at 11:21
  • 1
    Do you know there will be only one matching card? If not, where does gc: 3 come from in the result? The lowest rssi for one cardCode might be in a different record than the lowest rssi for another one. Commented Jun 17, 2019 at 11:23
  • no i don't know that what matching cards would be because cards array will be dynamic in each object of records Commented Jun 17, 2019 at 11:24
  • 1
    because code should compare and get matching records first so in my given data set only one object with cardCode : '12421' is there. Basically i want to match records on the basis of cardCode and you can see that object with 12421 is present in all three objects inside records and by comparing each object's rssi there is the minimum rssi of 13 with cardCode : 12421 Commented Jun 17, 2019 at 11:35

2 Answers 2

1

Updated

This version is based on the understanding reached after the long requirements discussion in the comments to the question. It does not use lodash. It's gotten complex enough that it probably should break into smaller pieces, and lodash might help with that.

It includes not just gc, but also time from the original records, and will, in fact, include anything else from there. If you want just gc, simply remove ...rest from the code.

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)
)

Original Answer

This is only a partial solution, to be updated if we can resolve the discussion in the comments. It fetches all the cards which appear in every record, and chooses the version with the lowest rssi. This may be close to the requirements, or it may not.

It doesn't use lodash. It might simplify a bit with lodash, but probably not very much.

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)
)

Sign up to request clarification or add additional context in comments.

2 Comments

Your solution is working perfectly but it can't giving gc inside result's each object. Result should look like this in first case [{"gc" : "3", cards : [{ "cardCode": "12421", "rssi": 13 }] } And in second case result should be [{ "gc" : "2", "cards" : [ { "cardCode": "6423", "rssi": 7 }] }, { "gc" : "3", "cards" : [ { "cardCode": "12421", "rssi": 13 }] } ]
@FahadHassanSubzwari: I wrote the version you saw before getting the full requirements. I even mentioned that in the text above. Since getting those requirements, I updated to the version that's now here.
0

With 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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.