1

I'm currently learning JS and I need a way to return an object that is similar to the given object but removing key/value pairs that have the same value (i.e. duplicates).

So if I had a given object { a: 1, b: 2, c: 3, d: 1 }:

it should return:

{b: 2, c: 3 }

Similarly, if all key-value pairs in an object had different values, the returned object would simply be the same as the given object.

I think I am close to solving it but I can't figure out what's wrong with my code. Any help would be much appreciated!

const noDuplicateValues = (obj) => {
  let result = {};
  let keys = Object.keys(obj);
  let duplicate;

  for(let i = 0; i < keys.length; i++) {
    for(let j = i +1; j < keys.length; j++) {
      duplicate = false;
      if(obj[keys[i]] === obj[keys[j]]) {
        duplicate = true;
      }
    }
    if(!duplicate) {
      result[keys[i]] = obj[keys[i]];
    } 
  }
  return result;
}
ruggle
  • 109
  • 1
  • 5
  • why it should remove `a` and `d` – brk Oct 24 '20 at 05:16
  • I'm doing an exercise that asks me to return an object that removes key-value pairs with the same value. Since a and d both have the value of 1, it will be removed from the returned object – ruggle Oct 24 '20 at 05:20

3 Answers3

1

I'd count up the number of occurrences of each value, then filter the object's entries by whether a given entry's value only occurs once:

const obj = { a: 1, b: 2, c: 3, d: 1 };
const occurrences = new Map();
for (const val of Object.values(obj)) {
  occurrences.set(val, (occurrences.get(val) || 0) + 1);
}
const newObj = Object.fromEntries(
  Object.entries(obj)
    .filter(([, val]) => occurrences.get(val) === 1)
);
console.log(newObj);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
0

To speed things up, your inner loop can exit as soon as it finds a duplicate. But the flaw which is preventing it from working correctly is that while it finds that a is a duplicate of d and correctly omits a, it doesn't omit d because when it checks d, which is the last element in the array, there are no subsequent elements to compare against, so it doesn't consider d to be a duplicate.

The fix is to make the inner loop check every element (not just the ones after the one being checked by the outer loop), of course being careful not to check an element against itself:

const noDuplicateValues = (obj) => {
    let result = {};
    let keys = Object.keys(obj);
    let duplicate;

    for (let i = 0; i < keys.length; i++) {
        duplicate = false;
        for (let j = 0; j < keys.length; j++) {
            if (
                i !== j // Don't compare an element with itself
                &&
                obj[keys[i]] === obj[keys[j]]
            ) {
                duplicate = true;
                break; // Found a dupe so we can stop checking this one for dupes
            }
        }
        if (!duplicate) {
            result[keys[i]] = obj[keys[i]];
        }
    }
    return result;
}

var x = noDuplicateValues({ a: 1, b: 2, c: 3, d: 1 });
console.log(x); // Object { b: 2, c: 3 }
kmoser
  • 8,780
  • 3
  • 24
  • 40
0

There are two issues with your code. First one is that the value of duplicate is set to false in the inner loop, it should be set in the outer loop instead. The secone issue is the inner loop only starts from i + 1. Therefore it actually does the following comparison:

  • a vs b, a vs c, a vs d
  • b vs c, b vs d
  • c vs d

So what you also need is to compare value of d vs a, b, c as well. So something like this should hopefully work.

const noDuplicateValues = (obj) => {
  let result = {};
  let keys = Object.keys(obj);
  let duplicate;

  for(let i = 0; i < keys.length; i++) { 
    duplicate = false;
    for(let j = 0; j < keys.length; j++) {
      
      if(i !== j && obj[keys[i]] === obj[keys[j]]) {
        duplicate = true;
      }
    }
    if(!duplicate) {
      result[keys[i]] = obj[keys[i]];
    } 
  }
  return result;
}

But it would be more efficient if you just keep track of the value and the number of occurrence: 1 : occur 2 times , 2 : 1 time, 3 : 1 time ... Then you can remove all the key-value pairs whose the value occur more than 1 time. This way you only need to loop through all the properties once.

Manh Quang
  • 91
  • 1
  • 9