2

I have an array of objects like so:

[
  {
    "id": "1",
    "location": "US"
  },
  {
    "id": "7",
    "location": "US"
  },
  {
    "id": "1",
    "location": "France"
  },
  {
    "id": "1",
    "location": "China"
  }
]

I would like to end up with a resulting array that looks like this:

[
  {
    "id": "1",
    "locations": ["US", "France", "China"]
  },
  {
    "id": "7",
    "locations": ["US"]
  }
]

Is there a solid way to accomplish this using underscore?

I'm contemplating looping through the array and for each id looping through the rest of the array and pushing location values to a locations array on that first object (by id), then at the end removing all duplicate objects (by id) which do not contain a locations property.

This is different from existing questions on SO that simply ask about removing duplicates. I am aiming to remove duplicates while also holding on to certain property values from these duplicates in an array on the 'surviving' object.

3
  • Native JS can handle this nicely, especially with some new ES6 features. Does it have to be underscore? Commented Dec 9, 2015 at 16:41
  • @SterlingArcher It dos not need to be underscore. I'm using underscore so just wanted to mention that in case there were ways to accomplish this easily using underscore methods. Commented Dec 9, 2015 at 16:42
  • Possible duplicate of Remove Duplicates from JavaScript Array Commented Dec 9, 2015 at 16:43

3 Answers 3

3

Solution in plain Javascript

var data = [{ "id": "9" }, { "id": "1", "location": "US" }, { "id": "7", "location": "US" }, { "id": "1", "location": "France" }, { "id": "1", "location": "China" }],
    result = [];

data.forEach(function (a) {
    a.location && !result.some(function (b) {
        if (a.id === b.id) {
            b.locations.push(a.location);
            return true;
        }
    }) && result.push({ id: a.id, locations: [a.location] });
});

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

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

3 Comments

if you wanted to remove all objects with repeating locations, could that be done with just one loop?
@Arrow, it should be possible, either by look up or with a Map/Set or an object as hash table. the decision between map and set, is if the locations are themself unique without id. if you need id as well, you need a map for grouping.
nice will attempt. I don't know how you feel about answering late questions, where there is already a selected answer. It is probably not worth your time, but I like how you solve these problems. The question is here if you are interested. stackoverflow.com/questions/44686078/…
1

You can use reduce function to transform your array.

var data = [
    { "id": "1", "location": "US" },
    { "id": "7", "location": "US" },
    { "id": "1", "location": "France" },
    { "id": "1", "location": "China" }
];

var result = data.reduce(function (prev, item) {
    var newItem = prev.find(function(i) {
        return i.id === item.id;
    });
    if (!newItem) {
        prev.push({id: item.id, locations: [item.location]});
    } else {
        newItem.locations.push(item.location);
    }
    return prev;
}, []);

Comments

1

And a version using underscore:

var result = _.chain(data)
    .groupBy('id')
    .map(function(group, id){
        return {
            id: id,
            locations: _.pluck(group, 'location')
        }
    })
    .value();

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.