1

I have an array of objects that looks like this:

[
{"name":"Andrea","from":"USA","Food":"Candy"},
{"name":"Matt","from":"Taiwan","Food":"Chicken"},
{"name":"Roddy","from":"USA","Food":"Rice"},
{"name":"Andy","from":"Great Britain","Food":"Steak"},
];

Is there a way to get the list of all countries from the array above, and get rid of the repeated ones?

So from the list above, the list I am to obtain is:

["USA", "Taiwan", "Great Britain"]

Thank you!

2
  • Is the Order of countries important? Commented Mar 20, 2015 at 14:24
  • No, the order of countries is not relevant. Commented Mar 20, 2015 at 14:33

4 Answers 4

4

Just loop over people and insert unique countries in a new array. Here is an example.

var countries = [];

var people = [
{"name":"Andrea","from":"USA","Food":"Candy"},
{"name":"Matt","from":"Taiwan","Food":"Chicken"},
{"name":"Roddy","from":"USA","Food":"Rice"},
{"name":"Andy","from":"Great Britain","Food":"Steak"},
];

for (var i = 0, l=people.length; i < l; i++) {
    if(people[i] && people[i].from) {//ensure country exists
        if (countries.indexOf(people[i].from) == -1) {//ensure unique
             countries.push(people[i].from);
        }
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Is it possible to avoid loop if I can use d3 object? In real like I have around 1000+ rows and I'm hoping to avoid looping over them.
@DanielKuo you will have to at least look at everyone of them one time to filter the duplicates, unless you are using a different data structure from the start .
@AbrahamAdam What if I just want all possible countries and leave the duplicates as they are?
You still can't avoid having to process every record to extract the from property value. Unless you change the format your data arrives in (e.g. it is grouped by country already), there is no shortcut to looping over the rows. It will be plenty fast for 1000+ rows, though.
3

Yet another variant with reduce

var arr = [
    {"name":"Andrea","from":"USA","Food":"Candy"},
    {"name":"Matt","from":"Taiwan","Food":"Chicken"},
    {"name":"Roddy","from":"USA","Food":"Rice"},
    {"name":"Andy","from":"Great Britain","Food":"Steak"},
];

var countries = arr.reduce(function(acc, cur){
                    if(!acc.map[cur.from]){
                        acc.map[cur.from]=true;
                        acc.result.push(cur.from);
                    }
                    return acc;
                }, {result:[], map:{}}).result;

var arr = [
    {"name":"Andrea","from":"USA","Food":"Candy"},
    {"name":"Matt","from":"Taiwan","Food":"Chicken"},
    {"name":"Roddy","from":"USA","Food":"Rice"},
    {"name":"Andy","from":"Great Britain","Food":"Steak"},
];

var countries = arr.reduce(function(acc, cur){
                    if(!acc.map[cur.from]){
                        acc.map[cur.from]=true;
                        acc.result.push(cur.from);
                    }
                    return acc;
                }, {result:[], map:{}}).result;

document.getElementById('countries').innerHTML = countries.join();
<span id="countries"></span>

5 Comments

Note that this does not work in ie8. Great solution otherwise!
Also, note this doesn't do away with looping over every record.
@GregL there is only one loop, without any loop impossible select unique elements from array.
Agreed, I was just highlighting to Daniel that even though there is no obvious loop here, it is still doing a loop under the covers in the reduce() call. He was hoping to avoid looping over the whole array altogether, but like you said, it is impossible.
I see. Thank you so much for all your help. Somehow I just failed to see the necessity to loop through all elements to get all possible values. Thanks a ton again.
2

If you are already using the excellent Lodash library, the following will do it for you neatly in one line:

var uniqueCountries = _(dataArray).pluck('from').unique().value();

UnderscoreJS has similar functionality using chaining.

For D3.js, the following will do it:

var uniqueCountries = d3.set(dataArray.map(function (x) { return x.from; })).values();

Without doing the unique-ifying on the server and returning that data separately, there is no way to get around looping through all records at least once to do this. For 1000 records or so, though, this will still be very fast. For plain JS, see other answers.

Comments

1

I'd loop over the Array and put the country into an array if it is not yet inside that array.

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.