3

Let's say we have an array that looks like this:

[
    {
        id: 0,
        name: 'A'
    },
    {
        id: 1,
        name:'A'
    },
    {
        id: 2,
        name: 'C'
    },
    {
        id: 3,
        name: 'B'
    },
    {
        id: 4,
        name: 'B'
    }
]

I want to keep only this objects that have the same value at 'name' key. So the output looks like this:

[
    {
        id: 0,
        name: 'A'
    },
    {
        id: 1,
        name:'A'
    },
    {
        id: 3,
        name: 'B'
    },
    {
        id: 4,
        name: 'B'
    }
]

I wanted to use lodash but I don't see any method for this case.

5
  • so, you want to keep object whose 'name' value exist in more than one object, right? Commented Sep 1, 2017 at 10:48
  • Could you clarify that? You only want to keep objects whose name exists at least twice in the array? Or that are grouped in pairs of two subsequent objects with the same name? Commented Sep 1, 2017 at 10:49
  • I only want to keep objects whose name exists at least twice in the array Commented Sep 1, 2017 at 10:50
  • @sympi Ah, okay, in this case, Rajesh’s answer should be the solution, though it doesn’t use lodash. Commented Sep 1, 2017 at 10:51
  • Is it important in which order the list every element comes? What happens if id:1 (name: 'A)' is id:5 instead? Commented Sep 1, 2017 at 10:58

4 Answers 4

9

You can try something like this:

Idea:

  • Loop over the data and create a list of names with their count.
  • Loop over data again and filter out any object that has count < 2

var data = [{ id: 0, name: 'A' }, { id: 1, name: 'A' }, { id: 2, name: 'C' }, { id: 3, name: 'B' }, { id: 4, name: 'B' }];

var countList = data.reduce(function(p, c){
  p[c.name] = (p[c.name] || 0) + 1;
  return p;
}, {});

var result = data.filter(function(obj){
  return countList[obj.name] > 1;
});

console.log(result)

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

2 Comments

To be honest, I did check your answer(more than once), and as always, its something that still goes over my head. Will read it few more times. ;-) Also will try to do it in 1 loop. Thanks for pointing out.
it works with empty arrays and if it is later valid, then it gets an element with update. concat filters empty elements.
5

A lodash approach that may (or may not) be easier to follow the steps of:

const originalArray = [{ id: 0, name: 'A' }, { id: 1, name: 'A' }, { id: 2, name: 'C' }, { id: 3, name: 'B' }, { id: 4, name: 'B' }];

const newArray =
      _(originalArray)
      	.groupBy('name') // when names are the same => same group.  this gets us an array of groups (arrays)
        .filter(group => group.length == 2) // keep only the groups with two items in them
        .flatten() // flatten array of arrays down to just one array
        .value();
        
console.log(newArray)
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

Comments

4

A shorter solution with array.filter and array.some:

var data = [ { ... }, ... ];  // Your array
var newData = data.filter((elt, eltIndex) => data.some((sameNameElt, sameNameEltIndex) => sameNameElt.name === elt.name && sameNameEltIndex !== eltIndex));
console.log("new table: ", newTable);

2 Comments

Nice solution, but the small size (long line) doesn't exactly help readability. The lambda with the some call could maybe be extracted to a named function?
Yes, named function can be used for these callbacks
2

You could use a hash table and a single loop for mapping the objects or just an empty array, then concat the result with an empty array.

var data = [{ id: 0, name: 'A' }, { id: 1, name: 'A' }, { id: 2, name: 'C' }, { id: 3, name: 'B' }, { id: 4, name: 'B' }],
    hash = Object.create(null),
    result = Array.prototype.concat.apply([], data.map(function (o, i) {
        if (hash[o.name]) {
            hash[o.name].update && hash[o.name].temp.push(hash[o.name].object);
            hash[o.name].update = false;
            return o;
        }
        hash[o.name] = { object: o, temp: [], update: true };
        return hash[o.name].temp;
    }));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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.