1

Given the array:

myArr = [
  {'a':1},
  {'b':1},
  {'b':2},
  {'a':1},
  {'b':2}
]

And the index 0, which has the object {'a':1}, I would like to get back the array: [{'b':1},{'b':2},{'b':2}] keeping the original sort order.

That is removing the object in index 0 and all other objects which are the equivalent. Is there an elegant way?

Fred J.
  • 5,759
  • 10
  • 57
  • 106
  • How would you know which object to remove? Would you pass a reference to remove or some value, like the array index for example? – nem035 Nov 08 '16 at 05:58
  • @nem035 I explained it a bit more. thx – Fred J. Nov 08 '16 at 06:00
  • Possible duplicate of [Javascript: How to filter object array based on attributes?](http://stackoverflow.com/questions/2722159/javascript-how-to-filter-object-array-based-on-attributes) – Rajesh Nov 08 '16 at 06:00
  • *"removing the object in index 0 and **all other objects which are the "same" value**"* is ambiguous. How would you determine this equality? Is comparing equality of direct (non prototype) properties enough? What if those properties are objects/functions/arrays themselves? – nem035 Nov 08 '16 at 06:02
  • @Rajesh: Not a duplicate, since you can get an arbitrary object where testing individual attributes is impractical. For example, testing for `obj.a == 1` will also remove `{ a: 1, x: 3 }`. – Amadan Nov 08 '16 at 06:07
  • @FredJ. Can you explain if you have an object like `{ a: 1, x: 3 }`, should it be removed? – Rajesh Nov 08 '16 at 06:14
  • @Rajesh no object like that and if so, should not be removed. – Fred J. Nov 08 '16 at 06:49

3 Answers3

4

If you want to remove the same object, it is simple:

    a1 = { a: 1 }
    b1 = { b: 1 }
    b2 = { b: 2 }
    myArr = [ a1, b1, b2, a1, b2 ]
    
    var filtered = myArr.filter(o => o != a1)
    console.log(filtered);
    // [ {b: 1}, {b: 2}, {b: 2} ]

However, if you want to remove an equivalent object, it gets complicated, because by default JavaScript does not have an object equivalence test. You can implement one yourself, or rely on one of the libraries like lodash:

var myArr = [
  {'a':1},
  {'b':1},
  {'b':2},
  {'a':1},
  {'b':2}
];

var filtered = _.filter(myArr, o => !_.isEqual(o, {a: 1}));
console.log(filtered);
// [ {b: 1}, {b: 2}, {b: 2} ]
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.6/lodash.min.js"></script>

Then again, if you're using lodash, you might as well just use it to the full extent:

var myArr = [
  {'a':1},
  {'b':1},
  {'b':2},
  {'a':1},
  {'b':2}
];

var filtered = _.differenceWith(myArr, [{a: 1}], _.isEqual);
console.log(filtered);
// [ {b: 1}, {b: 2}, {b: 2} ]
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.6/lodash.min.js"></script>

which basically does the same thing, but a bit more readably.

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • 1
    @Rajesh: I have already explained above how this is not at all a duplicate to the link you posted. Kindly desist. – Amadan Nov 08 '16 at 06:10
  • @Rajesh: Why would you remove `{a: 1, b: 2}` if `{a: 1}` "and all other objects which are the "same" value" are removed? `{a:1}` does not have the same value as `{a:1, b:2}`. "Remove the equivalent object" and "remove elements based on attributes" are two different problems; the OP was pretty clear in their intention. – Amadan Nov 08 '16 at 06:14
  • @Rajesh _"But still OP is looking for a way to filter array. and if there is an object `{a:1, b:2}`, then even that should be removed"_ That is not what requirement of Question is. OP does not ask to remove `b:2`. _"And the index 0, which has the object `{'a':1}`, I would like to get back the array: `[{'b':1},{'b':2},{'b':2}]` keeping the original sort order."_ Where does OP describe removing `b:2`? – guest271314 Nov 08 '16 at 06:16
0

This works for me

myArr = [
          {'a':1},
          {'b':1},
          {'b':2},
          {'a':1},
          {'b':2}
        ]

        //Get first item
        for(var key in myArr[0]){
            var firstItem = key;
        }
        alert('First item: ' + firstItem);

        //Remove matches
        var removedItems = []; //Not needed, just used to show you what it's removing.

        myArr.forEach(function(item){
            for (var key in item){
                if(key == firstItem){
                    removedItems.push(key); //Not needed
                    myArr.splice(item, 1); //Remove the array entry
                }
            }
        });
        alert('Removed items: ' + removedItems);
-3

try myArr.shift();

It will return {'a':1}

And myArr will be [{'b':1},{'b':2},{'b':2}]