Reputation: 118
Given an array of full names, where each name is in the format 'lastName, firstName', I want to find the completely unique names, i.e. given the names array below
const names = [
'Smith, Joan',
'Smith, John',
'Smith, Sam',
'Thomas, Joan',
'Upton, Joan',
'Upton, Tom',
'Vasquez, Cesar'
]
- Smith, John # Already saw a last name "Smith" - Smith, Sam # Already saw a last name "Smith" - Thomas, Joan # Already saw a first name "Joan" - Upton, Joan # Already saw a first name "Joan" - Upton, Tom # Already saw a last name "Upton"
I want to have as a result only
Smith, Joan
Vasquez, Cesar
This is the function I have so far. However, I'd like to rewrite it to avoid the nested for loops and improve performance.
function findUnique() {
const names = [
'Smith, Joan',
'Smith, John',
'Smith, Sam',
'Thomas, Joan',
'Upton, Joan',
'Upton, Tom',
'Vasquez, Cesar'
];
let result = names;
for (var i = 0; i < names.length; i++) {
for (var j = 1; j < names.length; j++) {
let names1 = names[i].split(', ');
let names2 = names[j].split(', ');
if (names1[0] == names2[0] || names1[0] == names2[1] || names1[1] == names2[0] || names1[1] == names2[1]) {
result.splice(i, 1);
}
}
}
return result;
}
Upvotes: 1
Views: 1270
Reputation: 19482
A solution using filter
and single Set
. Resulted array is directly returned. An element is added only if true
is returned from the callback.
const names = [
'Smith, Joan',
'Smith, John',
'Smith, Sam',
'Thomas, Joan',
'Upton, Joan',
'Upton, Tom',
'Vasquez, Cesar'
];
var n = new Set();
var unique = names.filter(function(name) {
var np = name.split(", ");
if (n.has(np[0]) || n.has(np[1])) {
return false;
}
n.add(np[0]).add(np[1]);
return true;
});
Upvotes: 0
Reputation: 17903
Remember what names we have seen using JavaScript object hashes. Then we can run through the array just a single time:
function findUnique() {
const names = [
'Smith, Joan',
'Smith, John',
'Smith, Sam',
'Thomas, Joan',
'Upton, Joan',
'Upton, Tom',
'Vasquez, Cesar'
];
firstNames = {}; // First names we have already seen.
lastNames = {}; // Last names we have already seen.
result = [];
for (var i = 0; i < names.length; i++) {
let splitName = names[i].split(', ');
let firstName = splitName[0];
let lastName = splitName[1];
// Check if we have seen either first name or last name.
if (!(firstNames[firstName] || lastNames[lastName])) {
// This is a "unique" name.
result.push(names[i]);
}
// Add names to lists of names we have seen.
firstNames[firstName] = true;
lastNames[lastName] = true;
}
return result;
}
console.log(findUnique());
Upvotes: 0
Reputation: 10823
This is how I would write it:
const names = [
'Smith, Joan',
'Smith, John',
'Smith, Sam',
'Thomas, Joan',
'Upton, Joan',
'Upton, Tom',
'Vasquez, Cesar'
];
const namesSeen = {};
const uniqueNames = [];
for (const name of names) {
const [last, first] = name.split(", ");
if (!namesSeen[first] && !namesSeen[last]) {
uniqueNames.push(name);
}
namesSeen[first] = true;
namesSeen[last] = true;
}
console.log(uniqueNames);
I noticed that you were using const
, so I used a few other ES6 features to make the code feel more natural: destructuring and for...of loops.
Upvotes: 1
Reputation: 8660
Use the Set object. It is specifically designed so that only one of each value can be put inside of it. It has the methods .has(value)
and .add(value)
I also use the for...of loop to take care of iterating through the list.
Demo: https://jsfiddle.net/6tq00maq/1/
const names = [
'Smith, Joan',
'Smith, John',
'Smith, Sam',
'Thomas, Joan',
'Upton, Joan',
'Upton, Tom',
'Vasquez, Cesar'
]
//set up lists for first and last names
var firstNameList = new Set();
var lastNameList = new Set();
//set place for unique names to be stored
var uniqueNames = [];
//iterate list
for (var name of names) {
var firstName = name.split(", ")[1];
var lastName = name.split(", ")[0];
//check if first name or last name are already indexed
if (!firstNameList.has(firstName) && !lastNameList.has(lastName)) {
//if not, push them to the unique names to return
uniqueNames.push(lastName + ", " + firstName);
}
//add to indexed names
firstNameList.add(firstName);
lastNameList.add(lastName);
}
console.log(uniqueNames);
Upvotes: 3