1

I have an array with duplicates:

nameList = [{name:"name1", filename:"filename1"}, {name:"name2", filename:"filename2"}, {name:"name3", filename:"filename2"}]

and I want to retain only the unique item but the last item only. I want:

nameList = [{name:"name1", filename:"filename1"}, {name:"name3", filename:"filename2"}]

I have tried:

var flags = {};
resultNameList = nameList.filter(function(entry) {
    if (flags[entry.filename]) {
        return false;
    }
    flags[entry.filename] = true;
    return true;
});

but it retains only the first occurrence of the duplicate. How can I get the last occurrence?

Please help. Thanks.

1
  • In the first object it key name is file. In rest of the object it is filename. Please confirm which one is correct Commented Jun 4, 2019 at 4:29

1 Answer 1

4

Reduce an object indexed by the filename property, overwriting the previous item at that key in the accumulator if it exists - this ensures that after all iterations, the object's values are composed only of the latest occurrence of a given filename. Then take the values of the accumulator:

const nameList = [{
  name: "name1",
  filename: "filename1"
}, {
  name: "name2",
  filename: "filename2"
}, {
  name: "name3",
  filename: "filename2"
}];

const output = Object.values(nameList.reduce((a, item ) => {
  a[item.filename] = item;
  return a;
}, {}));
console.log(output);

Note that key-value pairs in an object must be separated by :, not =.

The input given in the comment below looks to work as desired too:

const nameList = [{
  name: "name1",
  filename: "filename1"
}, {
  name: "name3",
  filename: "filename2"
}];

const output = Object.values(nameList.reduce((a, item) => {
  a[item.filename] = item;
  return a;
}, {}));
console.log(output);

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

4 Comments

Doesn't work. I only returns: {name:"name3", filename="filename2"}. What about {name:"name1",filename:"filename1"}, which is also unique?
I changed the first item from file to filename per you edit in the question, but it still looks to work as expected - just press the "Run code snippet" button as in the answer. The output is [ { "name": "name1", "filename": "filename1" }, { "name": "name3", "filename": "filename2" } ]. That's correct, isn't it?
I edited that input into a second snippet in the answer, but it looks to perform as desired too: press "Run code snippet" and you get [ { "name": "name1", "filename": "filename1" }, { "name": "name3", "filename": "filename2" } ]
Depending on the requirements, a better approach could be Array.from(nameList.reduce((result, object) => { result.set(object.filename, object); return result; }, new Map()).values());, using Map, so the order stays the same as in the original array and doesn’t change around due to Object key ordering semantics.

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.