0

I am trying to take an array of objects and do 2 things.

1.) Remove objects from the array that are duplicated, create a new array with the names of the items that were duplicates.

Original:

var duplicates = [];

var objects = [
    {
        name: 'foo',
        nums: [1,2]
    },
    {
        name: 'bar',
        nums: [3,2]
    },
    {
        name: 'baz',
        nums: [1,2]
    },
    {
        name: 'bum',
        nums: [2,3]
    },
    {
        name: 'bam',
        nums: [1,2]
    },
]

Desired Output:

duplicates = ['foo', 'baz', 'bam'];

objects = [
    {
        name: 'bar',
        nums: [3,2]
    },
    {
        name: 'bum',
        nums: [2,3]
    }
]

Can anyone help with this? I am using lodash in my project.

Scotty Bollinger
  • 2,343
  • 4
  • 19
  • 25
  • What if you have duplicates of both `[1,2]` and `[3,4]`? They all go into `duplicates`? – Barmar Jan 09 '15 at 01:22
  • When you say 'duplicate', do you mean the arrays are the same object, or that the arrays have the same length and order of items, or have the same length but not order of items? – Xotic750 Jan 09 '15 at 01:24
  • Isn't this the same question? http://stackoverflow.com/questions/27852356/finding-nested-duplicate-arrays-in-javascript-nested-array-uniq-in-lodash-unde – Xotic750 Jan 09 '15 at 01:24
  • @Barmar In my particular problem, there will never be multiple duplicates. I am dealing with a array of 3 sub arrays and while it's possible that all 3 match, in most cases, only 2 of them will match – Scotty Bollinger Jan 09 '15 at 16:43
  • @Xotic750 It's similar but it's actually the entire solution, and the other was a component of a certain way I was trying to solve my problem. Thought it beneficial to leave both. To answer your question, the order will always be the same so there would never be a [1,2] and a [2,1] and if so I would not want them to be counted as duplicates. – Scotty Bollinger Jan 09 '15 at 16:44
  • I see no real difference except you now have a different data structure. – Xotic750 Jan 09 '15 at 16:50

2 Answers2

1

If order of elements in nums array matters:

_.pluck(_.flatten(_.filter(_.groupBy(objects, "nums"), function(el) {
   return (el.length !== 1)
})), "name")

or a bit tidier

var hmap = _(objects).groupBy("nums").values();
var unique = hmap.where({'length': 1}).flatten().value();
var duplicates = hmap.flatten().difference(unique).value();
nullpotent
  • 9,162
  • 1
  • 31
  • 42
  • Thanks and this is very close. However, Your solution assumes I know the value of "1" in the duplicates. In my real-world scenario, I will not know any of the values to filter by. – Scotty Bollinger Jan 09 '15 at 16:40
0

I don't know underscore.js, here's how to do it with plain JS:

var counts = {};
var duplicates = [];
for (var i = 0; i < objects.length; i++) {
    var str = JSON.stringify(objects[i].nums);
    if (str in counts) {
        counts[str]++;
    } else {
        counts[str] = 1;
    }
}
objects = objects.filter(function(val) {
  if (counts[JSON.stringify(val.nums)] == 1) {
    return true;
  } else {
    duplicates.push(val.name);
    return false;
  }
});

DEMO

Barmar
  • 741,623
  • 53
  • 500
  • 612