Remove array duplicates by property javascript - javascript

I have a list of objects:
[{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}]
I need a simple way to filter out duplicates with regard to the name property, so:
[{name: "bob", age: "14"}, {name: "sue", age: "21"}]
There seem to be quite a few array duplicate removal questions, but not any based on a property. It can ignore all other fields.

Iterate the array, place all name values in a hash and skip objects whose name is already in the hash:
filterBy = function(ary, prop) {
var seen = {};
return ary.filter(function(item) {
var key = item[prop];
if(seen[key] === 1)
return false;
seen[key] = 1;
return true;
});
}
//
a = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}]
b = filterBy(a, 'name');
console.log(b);
ES6 version:
filterBy = function(ary, prop) {
var seen = new Set();
return ary.filter(item => !seen.has(item[prop]) && seen.add(item[prop]));
}
a = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}]
b = filterBy(a, 'name');
console.log(b);

You can do it with 2 for loops as follows. All you have to do is, keeping a result array and every time you insert into it, check whether the name attributes are equal.
function findDuplicate(){
var array= [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}];
var result=[];
for(x in array){
var found=false;
for(y in result){
if(result[y].name.localeCompare(array[x].name)==0){
found=true;
}
}
if(!found){
result.push(array[x]);
}
}
console.log(result);
}

You could do this with forEach and thisArg param.
var data = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}];
var result = [];
data.forEach(function(e) {
if (!this[e.name]) {
this[e.name] = e;
result.push(this[e.name]);
}
}, {});
console.log(result)
Or with forEach and map()
var data = [{name: "bob", age: "14"}, {name: "bob", age: "16"}, {name: "sue", age: "21"}], result =[];
data.forEach(function(e) {
if(result.map(a => {return a.name}).indexOf(e.name) == -1 ) result.push(e);
});
console.log(result)

You could use Array#filter and a this object for marking, if the same name is already filtered.
var array = [{ name: "bob", age: "14" }, { name: "bob", age: "16" }, { name: "sue", age: "21" }],
filtered = array.filter(function (a) {
if (!this[a.name]) {
this[a.name] = true;
return true;
}
}, Object.create(null));
console.log(filtered);

For the straightforward comparison in the Q., there are some
good answers here. If you want to provide a custom comparison
function that will work on e.g. object values, or that uses
a RegExp, then take a look at the following.
var dedupwhen = function(fn, list){
if(list[0] === undefined){
return [];
}
// Join the first item to the remainder that has had the first
// item filtered out (according to fn) and then been
// deduplicated itself.
return [list[0]].concat(dedupwhen(fn, list.slice(1).filter(function(item){
return !fn(list[0], item);
})));
};
var similarname = function(x,y){
return RegExp('^' + x.name + '$', 'i').test(y.name);
};
var list = [
{name: 'Sue', age: 44},
{name: 'Bob', age: "14"},
{name: 'bob', age: "16"},
{name: 'sue', age: "21"}
];
console.log(dedupwhen(similarname, list));

Related

Javascript filter array object inside non-array object

I have an object like this:
var obj = {name: 'Lesson I', author: [{name: 'Thomas', age: '40'}, {name: 'Richard', age: '33'}]}
I tried to filter the object to show only the author with age above 35. This is what I expected:
var obj = {name: 'Lesson I', author: [{name: 'Thomas', age: '40'}]}
However since the array is inside a non-array object, I cannot use filter() yet. How to approach this?
This is helpful in case you have more than one variable that keeps the same:
var obj = {name: 'Lesson I', author: [{name: 'Thomas', age: '40'}, {name: 'Richard', age: '33'}]}
obj = {
...obj,
author: obj.author.filter( x => x.age >= 35)
}
console.log(obj)
Although I recommend keeping the original obj and create a new one for the filtered obj:
var obj = {name: 'Lesson I', author: [{name: 'Thomas', age: '40'}, {name: 'Richard', age: '33'}]}
const above35 = {
...obj,
author: obj.author.filter( x => x.age >= 35)
}
console.log(obj,"and",above35)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
obj.author = obj.author.filter(checkAge); // this will return an array with 1 object.
function checkAge(author) {
return author.age >= 35;
}
One simple way would be like this:
var obj = {
name: "Lesson I",
author: [
{ name: "Thomas", age: "40" },
{ name: "Richard", age: "33" },
],
};
const result = obj.author.filter((ob) => ob.age > 35);
obj.author = result;
console.log(obj);
One way...declare a new object with each key/value of the original object, but filter() the author value:
let obj = {name: 'Lesson I', author: [{name: 'Thomas', age: '40'}, {name: 'Richard', age: '33'}]};
let obj_old_authors = {
name: obj.name,
author: obj.author.filter(author => 35 < author.age)
};
console.log(obj_old_authors);

I have an array of objects and will like to alter the value if the type is a number

I have this so far, but when I check people after it doesn't alter the age keys values to prepend "$".I want to assume I dont know which values are of type of number, so I want to do a check and change it to have $23, $3, $8 etc.
const people = [
{name: 'John', age: 23, sex: "male"},
{name: 'Andrew', age: 3, sex: "male"},
{name: 'Peter', age: 8, sex: "male"},
{name: 'Hanna', age: 14, sex: "male"},
{name: 'Adam', age: 37, sex: "male"}];
let indVals;
people.forEach(function(arr) {
indVals = Object.values(arr);
console.log('Individual values: ',indVals);
for(let val of indVals) {
if ( typeof val === "number") {
val = "$" + val;
}
}
});
You can map the people array and conditionally modify the value of a property in an object. Note that using map will give you a new array.
const people = [
{name: 'John', age: 23, sex: "male"},
{name: 'Andrew', age: 3, sex: "male"},
{name: 'Peter', age: 8, sex: "male"},
{name: 'Hanna', age: 14, sex: "male"},
{name: 'Adam', age: 37, sex: "male"}];
const result = people.map(obj => {
return Object.fromEntries(Object.entries(obj).map(([k, v]) => {
return (typeof v === 'number') ? [k, `$${v}`] : [k, v];
}));
});
console.log(result)
Since op stated that property names are not known. You need to use keys to get the properties then check the type and then update the value using the key.
const people = [
{name: 'John', age: 23, sex: "male"},
{name: 'Andrew', age: 3, sex: "male"},
{name: 'Peter', age: 8, sex: "male"},
{name: 'Hanna', age: 14, sex: "male"},
{name: 'Adam', age: 37, sex: "male"}];
people.forEach(obj=> {
Object.keys(obj).forEach(key=>{
if (typeof obj[key] === "number") {
obj[key] = "$" + obj[key];
}
});
});
console.log(people);
res = people.map((elem) => {
for(let key in elem){
if(typeof elem[key] == 'number'){
elem[key] += '$';
}
}
return elem;
})

how to transform an array to object

I'm trying to filter an array of objects of people into a new object with its property names arranged by age each in a separate array.
Example 1
Input:
groupAdultsByAgeRange([{name: "Henry", age: 9}, {name: "John", age: 20}])
Result:
{ '20 and younger': [ { name: 'John', age: 20 } ] }
Example 2
Input:
groupAdultsByAgeRange([{name: "Anna", age: 31}, {name: "John", age: 32}, {name: "Hank", age: 60}])
Result:
{
'31-40': [ { name: 'Anna', age: 31 }, { name: 'John', age: 32 } ],
'51 and older': [ { name: 'Hank', age: 60 } ]
}
If the age range is not in the input than it should not be part of the output. For example if the input does not have people with age 51 than the object should not contain property of '51 and older'. and if input us empty array than output should be an empty object.
Using lodash you can do something like this
const _ = require('lodash');
const array = [{name: "Anna", age: 31}, {name: "John", age: 32}, {name: "Hank", age: 60}];
function ageToRange(obj) {
const age = obj.age;
if (age <= 20) {
return '20 and younger';
}
if (age > 30 && age <= 40) {
return '31-40'
}
if (age > 50) {
return '51 and older';
}
}
const result = _.groupBy(array, ageToRange)
console.log(result);
This is how you do with native Javascript :
//example 1
let people1 = [{name: "Henry", age: 9}, {name: "John", age: 20}]
let younger_and_equal_20 = []
people1.forEach(e => {
if(e.age>=20){
younger_and_equal_20.push(e)
}
});
console.log({"20 and younger": younger_and_equal_20})
//example 2
let people2 = [{name: "Anna", age: 31}, {name: "John", age: 32}, {name: "Hank", age: 60}]
let data = {
"31-40" : [],
"51 and older" : []
}
people2.forEach(e => {
if(e.age>30 && e.age<=40){
data["31-40"].push(e)
}
else if(e.age>50){
data["51 and older"].push(e)
}
});
console.log(data)
let result = {}
function groupAdultsByAgeRange(people) {
// An array of object which represents people who are 20 or younger
const ageGroup = people.filter(person => person.age <= 20)
// Only add array to the object key if it's not empty
if (ageGroup.length > 0) {
result["20 and younger"] = ageGroup
}
return result;
}

An array of objects that checks each object age and then returns the name of all objects that meet that age

I had this question on an exam and I got it wrong and I have been trying my best reading through MDN Web Docs but being only a week into learning JavaScript I have no clue what I am looking for.
This what I can recall from my exam, it this fictional state only 15-year-olds and above can be babysitters. I had used a ".find()" and I only could produce 1 person and it gave me the whole object and they just wanted the name. Gave a day in a half to find the answer myself but I am lost. HELP!
If you also have a link so I can read up more on this it will be helpful, because other students said they had similar and they asked them to average all the age instead. Arrays and Objects have me wanting to bang my head against the wall already.
function legalBabysitter(sitters){
};
/*Do not modify anything below this line*/
const babysitterArray = [
{name: 'Peter', age: 13},
{name: 'Paul', age: 15},
{name: 'Mary', age: 17}
];
console.log(legalBabysitter(babysitterArray)); // should produce [Paul, Mary]
You can use fitler and map like this return sitters.filter(c=>c.age >= 15).map(c=>c.name);
function legalBabysitter(sitters){
return sitters.filter(c=>c.age >= 15).map(c=>c.name);
};
/*Do not modify anything below this line*/
const babysitterArray = [
{name: 'Peter', age: 13},
{name: 'Paul', age: 15},
{name: 'Mary', age: 17}
];
console.log(legalBabysitter(babysitterArray)); // should produce [Paul, Mary]
If you need only for exam, you can use for loop, it is very clear.
function legalBabysitter(sitters){
var result = [];
for(var i =0; i < sitters.length; i ++){
if(sitters[i].age >= 15){
result.push(sitters[i].name);
}
}
return result;
};
function legalBabysitter(sitters){
var result = [];
for(var i =0; i < sitters.length; i ++){
if(sitters[i].age >= 15){
result.push(sitters[i].name);
}
}
return result;
};
/*Do not modify anything below this line*/
const babysitterArray = [
{name: 'Peter', age: 13},
{name: 'Paul', age: 15},
{name: 'Mary', age: 17}
];
console.log(legalBabysitter(babysitterArray)); // should produce [Paul, Mary]
const babysitterArray = [
{name: 'Peter', age: 13},
{name: 'Paul', age: 15},
{name: 'Mary', age: 17}
];
function legalBabysitter(sitters){
return sitters.filter(_ => _.age > 14).map(_ => _.name)
};
console.log(legalBabysitter(babysitterArray))
If you don't know .filer and .reduce, you can do it by .forEach.
const babysitterArray = [
{name: 'Peter', age: 13},
{name: 'Paul', age: 15},
{name: 'Mary', age: 17}
];
function legalBabysitter(sitters){
let target = [];
sitters.forEach(_ => {
if (_.age > 14) target.push(_.name)
})
return target;
};
console.log(legalBabysitter(babysitterArray))
You can use reduce
Here idea is
Loop through array
Check if age is greater than or equal to 15 than add name to op
else keep it as it is
return op from function
function legalBabysitter(sitters){
return sitters.reduce((op,inp)=>{
if(inp.age >= 15){
op.push(inp.name)
}
return op
},[])
};
/*Do not modify anything below this line*/
const babysitterArray = [
{name: 'Peter', age: 13},
{name: 'Paul', age: 15},
{name: 'Mary', age: 17}
];
console.log(legalBabysitter(babysitterArray)); //

return the length of an array with the condition in it

function(people){
}
people([{name: 'John', age: 22},{name: 'paul', age: 23},{name: 'mathew', age: 24},])
How to return the length of an array consisting of person age more than 22 years old which should be 2.
You can use array reduce to count:
function people(array){
return array.reduce((total, current)=>{
if(current.age>22)
total = total +1;
return total;
},0);
}
console.log(people([{name: 'John', age: 22},{name: 'paul', age: 23},{name: 'mathew', age: 24},]));
Below is the functional programming approach to your question:
const persons = [
{name: 'John', age: 22},
{name: 'paul', age: 23},
{name: 'mathew', age: 24}
]
const over22 = persons.filter(person => person.age > 22)
console.log('there are', over22.length, 'people aged over 22')
Hope this helps.
Cheers,
Please try following :
function find_length(checkField, valueField, myArray) {
for (var i = 0; i < myArray.length; i++) {
if (myArray[i][checkField] == valueField) {
return Object.keys(myArray[i]).length;
}
}
}
var myList = [{name: 'John', age: 22}, {name: 'paul', age: 23}, {name: 'mathew', age: 24},];
var ageObjLength = find_length('age', '22', myList );
alert("Length is " + ageObjLength);

Categories