Dan Mishin
Dan Mishin

Reputation: 117

remove object from array where one key is duplicate and another key less then other

I have this array with objects:

var data=[
    { number: '31907411282', unix_date: '1547012427' },
    { number: '31907411282', unix_date: '1547013214' },
    { number: '31907514691', unix_date: '1547015155' },
    { number: '31907514691', unix_date: '1547015232' },
    { number: '31907514691', unix_date: '1547016134' },
    { number: '31907514691', unix_date: '1547016443' },
    { number: '31907638716', unix_date: '1547017122' },
    { number: '31907644067', unix_date: '1547017381' }
]

How I can remove duplicate objects with newer date and get new array like this:

var new_data=[
    { number: '31907411282', unix_date: '1547012427' },
    { number: '31907514691', unix_date: '1547015155' },
    { number: '31907638716', unix_date: '1547017122' },
    { number: '31907644067', unix_date: '1547017381' }
]

I can't understand how to do all procedure. Thanks

UPDATE

I try this construction:

  1. firstly we need group and sort objects
  2. second step is get first object from grouped and push to new array

Code:

var data=[
    { number: '31907411282', unix_date: '1547012427' },
    { number: '31907411282', unix_date: '1547013214' },
    { number: '31907514691', unix_date: '1547019134' },
    { number: '31907514691', unix_date: '1547015232' },
    { number: '31907514691', unix_date: '1547016134' },
    { number: '31907514691', unix_date: '1547016443' },
    { number: '31907638716', unix_date: '1547017122' },
    { number: '31907644067', unix_date: '1547017381' }
]

var new_data=[];
var groupByNumber=groupBy(data, 'number');
for(i in groupByNumber){
    var sort_arr=groupByNumber[i].sort(compare)
    new_data.push(sort_arr[0])
}

console.log(new_data)

function compare(a, b) {
  let comparison = 0;
  if (a.unix_date > b.unix_date) {
    comparison = 1;
  } else if (a.unix_date < b.unix_date) {
    comparison = -1;
  }
  return comparison;
}

function groupBy(xs, key) { //group by key
    return xs.reduce(function(rv, x) {
        (rv[x[key]] = rv[x[key]] || []).push(x);
        return rv;
    }, {});
};

Maybe it can be more elegant

UPDATE 2

@miroslav-glamuzina give more elegance way:

let filtered = data.reduce((acc, item) => {
  if (!acc.some((e, i) => {
      if (item.number === e.number) {
        if (item.unix_date < e.unix_date) {
          acc.splice(i, 1, item);
        }
        return true;
      }
    })) {
    acc.push(item);
  }
  return acc;
}, []);

Upvotes: 3

Views: 92

Answers (3)

djheru
djheru

Reputation: 3719

Sort the items by date, reduce the array, keeping only the elements that have a number that does not already exist in the accumulator array.

let data = [{
      number: '31907411282',
      unix_date: '1547013214'
    },
    {
      number: '31907411282',
      unix_date: '1547012427'
    },
    {
      number: '31907514691',
      unix_date: '1547015155'
    },
    {
      number: '31907514691',
      unix_date: '1547015232'
    },
    {
      number: '31907514691',
      unix_date: '1547016134'
    },
    {
      number: '31907514691',
      unix_date: '1547016443'
    },
    {
      number: '31907638716',
      unix_date: '1547017122'
    },
    {
      number: '31907644067',
      unix_date: '1547017381'
    }
    ];

    let filtered = data
      .sort((a, b) => (a.unix_date > b.unix_date) ? 1 : -1)
      .reduce((acc, item) => {
        if (!acc.find(el => el.number === item.number)) {
          acc.push(item)
        }
        return acc
      }, []);

      console.log(filtered);

Upvotes: 1

Miroslav Glamuzina
Miroslav Glamuzina

Reputation: 4557

You can use reduce to achieve this:

var data = [{
    number: '31907411282',
    unix_date: '1547013214'
  },
  {
    number: '31907411282',
    unix_date: '1547012427'
  },
  {
    number: '31907514691',
    unix_date: '1547015155'
  },
  {
    number: '31907514691',
    unix_date: '1547015232'
  },
  {
    number: '31907514691',
    unix_date: '1547016134'
  },
  {
    number: '31907514691',
    unix_date: '1547016443'
  },
  {
    number: '31907638716',
    unix_date: '1547017122'
  },
  {
    number: '31907644067',
    unix_date: '1547017381'
  }
];

let filtered = data.reduce((acc, item) => {
  if (!acc.some((e, i) => {
      if (item.number === e.number) {
        if (item.unix_date < e.unix_date) {
          acc.splice(i, 1, item);
        }
        return true;
      }
    })) {
    acc.push(item);
  }
  return acc;
}, []);

console.log(filtered);

Hope this helps,

Upvotes: 1

tam.dangc
tam.dangc

Reputation: 2032

You can use reduce to loop through the array and store a set of keys(number) to check if this exists. Then push into the new array.

var data=[
    { number: '31907411282', unix_date: '1547012427' },
    { number: '31907411282', unix_date: '1547013214' },
    { number: '31907514691', unix_date: '1547015155' },
    { number: '31907514691', unix_date: '1547015232' },
    { number: '31907514691', unix_date: '1547016134' },
    { number: '31907514691', unix_date: '1547016443' },
    { number: '31907638716', unix_date: '1547017122' },
    { number: '31907644067', unix_date: '1547017381' }
]
const rs = data.reduce((acc, e) => {
  if(!acc.number.has(e.number)) {
    acc.newData.push(e)
    acc.number.add(e.number)
  }
  return acc
}, {number: new Set(), newData: []})

console.log(rs.newData)

Upvotes: 2

Related Questions