Home > Software engineering >  Filtering objects that has unique combination of values
Filtering objects that has unique combination of values

Time:08-10

I've got an array of objects that look like this:

[{"Account Name":"John Hill","Account Type":"Services","Organization":"A","Account Address":"2 Westall Rd"},
{"Account Name":"John Hill","Account Type":"Training","Organization":"A","Account Address":"2 Westall Rd"},
{"Account Name":"Dave Butcher","Account Type":"Engieering","Organization":"A","Account Address":"Level 1/55 Sunshine Blvd"},
{"Account Name":"Jake Wellington","Account Type":"Management","Organization":"A","Account Address":"11 Maroochy Rd},
{"Account Name":"Jake Wellington","Account Type":"Management","Organization":"A","Account Address":"11 Maroochy Rd"}]

From the objects above, there's some duplicate account names, but they're unique due to the account type. I'm trying to figure out a way to filter it so that a combination of key values would make an object unique, rather than a single key. Something like filtering the Account Name && Account Type.

I've also noticed some solutions would create a new array and include only the keys to filter, but I'd like the solution to preserve all keys from an object rather than creating a new object with lesser keys.

Expected result would look like this:

[{"Account Name":"John Hill","Account Type":"Services","Organization":"A","Account Address":"2 Westall Rd"},
{"Account Name":"John Hill","Account Type":"Training","Organization":"A","Account Address":"2 Westall Rd"},
{"Account Name":"Dave Butcher","Account Type":"Engieering","Organization":"A","Account Address":"Level 1/55 Sunshine Blvd"},
{"Account Name":"Jake Wellington","Account Type":"Management","Organization":"A","Account Address":"11 Maroochy Rd}]

CodePudding user response:

const array = [{"Account Name":"John Hill","Account Type":"Services","Organization":"A","Account Address":"2 Westall Rd"},
{"Account Name":"John Hill","Account Type":"Training","Organization":"A","Account Address":"2 Westall Rd"},
{"Account Name":"Dave Butcher","Account Type":"Engieering","Organization":"A","Account Address":"Level 1/55 Sunshine Blvd"},
{"Account Name":"Jake Wellington","Account Type":"Management","Organization":"A","Account Address":"11 Maroochy Rd"},
{"Account Name":"Jake Wellington","Account Type":"Management","Organization":"A","Account Address":"11 Maroochy Rd"}]

const filteredArr = array.reduce((acc, current) => {
  const x = acc.find(item => (item['Account Name'] === current['Account Name'] ) && (item['Account Type'] === current['Account Type']));
  if (!x) {
    return acc.concat([current]);
  } else {
    return acc;
  }
}, []);

console.log(filteredArr);

CodePudding user response:

Use a Map. Loop over the array and on each iteration create a key from the Account Name and Account Type, and set the whole object as its value. Finally use values() to return a deduped array.

const data=[{"Account Name":"John Hill","Account Type":"Services",Organization:"A","Account Address":"2 Westall Rd"},{"Account Name":"John Hill","Account Type":"Training",Organization:"A","Account Address":"2 Westall Rd"},{"Account Name":"Dave Butcher","Account Type":"Engieering",Organization:"A","Account Address":"Level 1/55 Sunshine Blvd"},{"Account Name":"Jake Wellington","Account Type":"Management",Organization:"A","Account Address":"11 Maroochy Rd"},{"Account Name":"Jake Wellington","Account Type":"Management",Organization:"A","Account Address":"11 Maroochy Rd"}];

const map = new Map();

for (const obj of data) {
  const key = `${obj['Account Name']}-${obj['Account Type']}`;
  map.set(key, obj);
}

console.log([...map.values()]);

CodePudding user response:

You can use the hash group approach to filter by several properties:

const data = [{"Account Name":"John Hill","Account Type":"Services","Organization":"A","Account Address":"2 Westall Rd"},{"Account Name":"John Hill","Account Type":"Training","Organization":"A","Account Address":"2 Westall Rd"},{"Account Name":"Dave Butcher","Account Type":"Engieering","Organization":"A","Account Address":"Level 1/55 Sunshine Blvd"},{"Account Name":"Jake Wellington","Account Type":"Management","Organization":"A","Account Address":"11 Maroochy Rd"},{"Account Name":"Jake Wellington","Account Type":"Management","Organization":"A","Account Address":"11 Maroochy Rd"}];

const uniqHashes = data.reduce((acc, item) => {
    const hash = [item['Account Name'], item['Account Type']].join('-');
    acc[hash] ??= item
    return acc;
}, {});

const uniqs = Object.values(uniqHashes);

console.log(uniqs);
.as-console-wrapper { max-height: 100% !important; top: 0 }

CodePudding user response:

Use the uniqueness of the keys of the js objects

function filterDuplicates(arr){
    let o ={}
    arr.forEach(e => {
        // check all object
        //o[JSON.stringify(e)]=e;
        // check only acc name and type 
        o[e['Account Name'] e['Account Type']]=e;
    });
    return Object.values(o);
}

CodePudding user response:

This solution tries to keep it simple. We collect all distinct rows into a new array and check, before adding, if a 'equivalent' row is already there. Time complexity is O(n^2). So probably not optimal for really large tables, where one should prefer a solution like offered by @Andy above (using composed keys and a map - that's O(n))

const array = [{"Account Name":"John Hill","Account Type":"Services","Organization":"A","Account Address":"2 Westall Rd"},
  {"Account Name":"John Hill","Account Type":"Training","Organization":"A","Account Address":"2 Westall Rd"},
  {"Account Name":"Dave Butcher","Account Type":"Engieering","Organization":"A","Account Address":"Level 1/55 Sunshine Blvd"},
  {"Account Name":"Jake Wellington","Account Type":"Management","Organization":"A","Account Address":"11 Maroochy Rd"},
  {"Account Name":"Jake Wellington","Account Type":"Management","Organization":"A","Account Address":"11 Maroochy Rd"}]

const distinctRows = []
array.forEach((thisRow) => {
  if (distinctRows.find((otherRow) => (thisRow['Account Name'] === otherRow['Account Name'] ) && (thisRow['Account Type'] === otherRow['Account Type'])) === undefined) {
    distinctRows.push(thisRow);
  }
})

console.log(distinctRows);

  • Related