1

This is a follow up post from Compare key values within object for duplicate for a follow up answer.

I have an object:

myObj = {
  attendent-0-id:"123",
  attendent-0-name:"Bob Smith",
  attendent-1-id:"1234",
  attendent-1-name:"Alex Smith",
  attendent-2-id:"123",
  attendent-2-name:"Charlie Smith",
  attendent-0-id:"123",
  attendent-0-name:"John Smith",
  attendent-maxGuest:1,
  attendent-party-name:"",
}

Thanks to help on here (Rick) I was able to get 90% of the way there.

function errorOnDuplicateIds(obj) {
  const map = {};
  const pattern = /^attendent-\d+-id$/;

  for (const key of Object.keys(obj)) {
    if (pattern.test(key)) {      
      const value = obj[key]

      if (value in map) {
        map[value] = [map[value], key];       
      } else {
        map[value] = key
      }
    }    
  }
return map;
}

I am getting a return of:

array:[
  0:(2) ["attendent-0-name", "attendent-1-name"]
  1:"attendent-2-name"
]

but I am looking for:

array:[
  0:(2) ["attendent-0-name", "attendent-1-name", "attendent-2-name"]
]

The issue I am having is that while this works if there are two matching keys it will not work (Correctly) if there are three or more.

6
  • 1
    I believe you should have edited your original question, not create another one. Commented Aug 1, 2018 at 15:13
  • Sounds like you shouldn't have accepted an answer that doesn't work? Commented Aug 1, 2018 at 15:13
  • 1
    It did work for what I needed but things have changed. The person who provided said answer asked for a new question to keep things separate. Commented Aug 1, 2018 at 15:19
  • It would help to know why it is not working Correctly. What are the expected results when there are three or more of the same id and what is actually given? Commented Aug 1, 2018 at 15:22
  • What is the desired behavior when there is more than one match? Commented Aug 1, 2018 at 15:22

1 Answer 1

2

If you want to have an array of all matches for each key in you map, you need to start by setting an array when you find a key the first time. On subsequent matches, just push into that array:

const myObj = {'attendent-0-id': "1234",'attendent-0-name': "Bob Smith",'attendent-1-id': "123",'attendent-1-name': "Alex Smith",'attendent-2-id': "123",'attendent-2-name': "Charlie Smith",'attendent-maxGuest': 1,'attendent-party-name': "",};
  
function errorOnDuplicateIds(obj) {
  const map = {};
  const pattern = /^attendent-\d+-id$/;

  for (const key of Object.keys(obj)) {
    if (pattern.test(key)) {
      const value = obj[key]

      if (value in map) {
        map[value].push(key); // push a new value 
      } else {
        map[value] = [key] // set it to an array
      }
    }
  }

  /* if you only want lengths > 1
     otherwise just return map   */
  let filtered = Object.entries(map)
    .reduce((a, [key, value]) =>  value.length > 1 ? Object.assign(a, {[key]: value}) : a, {})

  return filtered;
}

console.log(errorOnDuplicateIds(myObj));

If you are only interested in values with more than one hit, you can reduce() down to a map with only values of length greater than one, which is what the last bit in the snippet does.

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

3 Comments

Great @RyleyAmeden, note that this will return all values even those with only one ID. I added an edit that shows a quick way to filter to only dupes.
I noticed that, thank you! It is giving me an error that .length doesn't exists on {}
@RyleyAmeden maybe your passing in the wrong thing, not sure. I added it to the snippet so you can see it in action.

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.