1

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-maxGuest:1,
  attendent-party-name:"",
}

I need to create a loop that go through myObj and find all the id's and then compares them for duplicates. So in this case it would log an error because attendent-0-id is equal to attendent-2-id.

If I do find duplicates I need to set a flag to true;

I have tried a bunch of things and am just stuck at this point. Thanks for any help.

3
  • 3
    Numbered properties? Don't do that, use a structure with an array of objects. Commented Jul 30, 2018 at 19:35
  • Please post the bunch of things you tried so that you can help you finding what went wrong. Commented Jul 30, 2018 at 19:36
  • You want to get keys of duplicate values or just true or false for duplicity? What is the result you are expecting? Commented Jul 30, 2018 at 19:37

5 Answers 5

2

In your case you can go through myObj using Object.keys() via:

for (const key of Object.keys(obj))

use a plain object as a map to store the previous values of the ids:

const map = {};

use a regex pattern to make sure only the specific ids are evaluated:

const pattern = /^attendent-\d+-id$/;

and then with the help of the map, log the error on duplicate ids:

if (value in map) {
  console.error(`${map[value]} is equal to ${key}, which is ${value}`);        
}

Example:

const 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-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) {
        console.error(`${map[value]} is equal to ${key}, which is ${value}`);        
      } else {
        map[value] = key
      }
    }    
  }
}

errorOnDuplicateIds(myObj);

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

6 Comments

Thank you. Being able to filter by "pattern" was extremely helpful
Was wondering if I could ask a follow up. This work perfectly if there are two matches but if there are three it doesn't. It doesn't add the third to the array.
Sure @RyleyAmeden, create a new post about it and I or someone else will give you an updated/better solution according to your needs. Please, make this and other additional information clearly stated in the new post. ;)
@RyleyAmeden What do you mean by "It doesn't add the third to the array."?
|
1
const ids = []; // keep track of found ids
Object.keys(myObj).forEach(key => { // iterate over all properties of myObj
    // check if property name is in format "attendent-" *some number* "-id"
    if (/^attendent-\d+-id$/.test(key)) {
        // check if the id has already been found
        if (ids.findIndex(id => id === myObj[key]) !== -1) {
            console.log('error');
        } else {
            ids.push(myObj[key]);
        }
    }
});

Comments

1

You can use Object.entries and a Map (keyed by value) for this:

var 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-maxGuest":1, "attendent-party-name":""};

var dupes = [...Object.entries(myObj).reduce(
    (map, [key,val]) => map.set(val, (map.get(val) || []).concat(key)), 
    new Map
).values()].filter(keys => keys.length > 1);

console.log(dupes);

This solution does not give any particular meaning to the format of the keys.

Having said that, your object structure looks suspicious of bad design: you should not have enumerations in your object keys. For that you should use arrays.

Comments

1

Object.values(myObj) will create an array of all values and then you can use any way to find duplicate elements in that array.

var myValues = Object.values(myObj); //This will create an array of all values
var uniq = myValues.map((val) => {
  return {count: 1, val: val}
}).reduce((a, b) => {
  a[b.val] = (a[b.val] || 0) + b.count
  return a
}, {});
var duplicates = Object.keys(uniq).filter((a) => uniq[a] > 1)
if (duplicates.length) {
   return true;
} else {
   return false;
}

Comments

1

My first advice would be to redefine your object to something more flexible.

let myObject = {
    attendants : [
        { 
            id: "123",
            name: "Bob Smith"
        },
        { 
            id: "456",
            name: "Alex Smith"
        },
        { 
            id: "768",
            name: "Charlie Smith"
        },           
    ],
    maxGuest: 1,
    partyName: ""
};

This will allow you to iterate the attendants.

for (var attendant in myObject.attendants){
     doSomething(attendant.id, attendant.name);
}

You can also sort the attendant:

// Sort by id 
myObject.attendants.sort(function(left, right){
    return left.value - right.value;
});

// Sort by name
myObject.attendants.sort(function (left, right){
    var leftName = left.name.toLowerCase();
    var rightName = right.name.toLowerCase();

    if (leftName < rightName) return -1;
    if (leftName > rightName) return 1;
    return 0;
});

Now, lets assume you don't have a choice. Then it gets complicated.

You need to create (or modify an existent) a sort algorithm so it can use keys that are generated as:

myObject[`attendent-${index}-id`]
myObject[`attendent-${index}-name`]

and keep the pair

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.