JS - Sorting array of objects - javascript

I'm trying to sort an array of objects in JS, but for some reason it doesnt work :(
This is the code I'm running:
let myArr = [{"name": "a", "age": 21}, {"name": "b", "age": 18}, {"name": "c", "age": 20}];
console.log(myArr.sort((a, b) => {
return a["age"] > b["age"];
}))
The output is the same array as it was declared:
[
{ name: 'a', age: 21 },
{ name: 'b', age: 18 },
{ name: 'c', age: 21 }
]
When I looked it up it seemed like it's written as it should, not really sure what went wrong.
Any idea what I did wrong?

Use - instead of >. It should return a Number type rather than Boolean type. see sort on mdn
let myArr = [
{ name: "a", age: 21 },
{ name: "b", age: 18 },
{ name: "c", age: 20 },
];
console.log(
myArr.sort((a, b) => {
return a["age"] - b["age"];
})
);
Using one-liner syntax using arrow function
let myArr = [
{ name: "a", age: 21 },
{ name: "b", age: 18 },
{ name: "c", age: 20 },
];
console.log(myArr.sort((a, b) => a.age - b.age));

Related

How to remove a property from array of objects [duplicate]

This question already has answers here:
Remove property for all objects in array
(18 answers)
Closed 1 year ago.
I have an array of objects with name and age property:
[
{ name: "Matthew", age: 23 },
{ name: "James", age: 20 },
{ name: "Daniel", age: 25 },
{ name: "Joshua", age: 22 }
]
I want to remove age property from all of the objects and print in console like
[
{ name: "Matthew" },
{ name: "James" },
{ name: "Daniel" },
{ name: "Joshua" }
]
Iterate over your array and use delete keyword.
let array = [
{ name: "Matthew", age: 23 },
{ name: "James", age: 20 },
{ name: "Daniel", age: 25 },
{ name: "Joshua", age: 22 }
]
array.forEach(function(v){ delete v.age });
console.log(array);
You can use map function to achieve this.
let output = test.map(({name}) => ({name}));
If you want to filter with multiple object you can add after name like {name, salary}
var test =[
{ name: "Matthew", age: 23 },
{ name: "James", age: 20 },
{ name: "Daniel", age: 25 },
{ name: "Joshua", age: 22 }
];
let output = test.map(({name}) => ({name}));
console.log(JSON.stringify(output, null, 2));
const newData = oldData.map(item=>({name:item.name}))

manipulating array of json data

I have a project where I have to take some data from a GoogleSheet document and send it to database.
I get the data from googlesheet document, but the problem is how is the data structured.
[
{
class: "A",
name: "Alex",
age: 13
},
{
class: "A",
name: "Mary",
age: 14
},
{
class: "B",
name: "John",
age: 13
},
{
class: "B",
name: "William",
age: 12
}
]
The problem is I want my JSON object to look like this
[
"A": {
{
name: "Alex",
age: 13
},
{
name: "Mary",
age: 13
}
},
"B": {
{
name: "John",
age: 13
},
{
name: "William",
age: 13
}
}
]
Any idea how can I do that? I want to group my objects over an element, like the class. All the people with the same class value to be in the same group/json.
You can make use of Array.reduce and format it.
let data = [{class:"A",name:"Alex",age:13},{class:"A",name:"Mary",age:14},{class:"B",name:"John",age:13},{class:"B",name:"William",age:12}];
//destructuring and renaming it to `_` as `class` is a pre-defined identifier in javascript
const formatData = (data) => data.reduce((res, {
class: _,
...rest
}) => {
//(res[_] || []) --> If the `class` prop is not already present in the res object, then using empty array
//If already present spreading res[_] and adding the current object to the existing array
res[_] = [...(res[_] || []), { ...rest }]
return res;
}, {})
console.log(formatData(data))
.as-console-wrapper {
max-height: 100% !important;
}
You can have a look at Destructuring Assignment for more info about destructuring and assigning new variable names.

Rename value if it is duplicate in json -

When there are multiple entries, I only want to append "_1","_2"....etc to json object, making sure no data is lost. If this is input:
names_array = [
{name: "a", age: 15},
{name: "a", age: 16},
{name: "a", age: 17},
{name: "b", age: 18}
{name: "b", age: 19}];
I want the output to be
names_array_new = [
{name: "a", age: 15},
{name: "a_1", age: 16},
{name: "a_2", age: 17},
{name: "b", age: 18}
{name: "b_1", age: 19}
];
I have searched for this but only found how to remove duplicates when entire objects are same or retain the last found value.
there are possibly better solutions, but i came up with such quick snippet. take it and make better.
name_changer = (n) => {
splitted = n.split("_");
if(splitted.length > 1) {
name = splitted[0];
ord = parseInt(splitted[1]);
return `${name}_${ord+1}`
} return `${n}_${1}`
}
stack = []
names_array = [
{name: "a", age: 15},
{name: "a", age: 16},
{name: "a", age: 17},
{name: "b", age: 18},
{name: "b", age: 19}
];
names_array.forEach(obj => {
if (stack.indexOf(obj.name) > -1) {
obj.name = name_changer(obj.name);
} stack.push(obj.name);
})
console.log(names_array);
You can use the function Array.prototype.reduce to generate the desired output.
The handler basically keeps the previous processed values in order to save the current count and finally we get the result from the accumulator.
let arr = [ {name: "a", age: 15}, {name: "a", age: 16}, {name: "a", age: 17}, {name: "b", age: 18}, {name: "b", age: 19}],
{result} = arr.reduce((a, {name: n, age}) => {
let key = a.counts[n] = (a.counts[n] || a.counts[n] === "" ? (+a.counts[n] + 1) : ""),
name = `${n}${key === "" ? "" : "_"}${key}`;
a.result.push({name, age});
return a;
}, {counts: {}, result: []});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can simply check the index and name of each a and b and then rename the value of that object keys with count++ with increment of count on each loop.
Just FYI - This can be improved more so wait for other solutions to come as well and choose what suits you best but this is simple and straight to your desired output!
Expected Output Demo:
var names_array = [{
name: "a",
age: 15
},
{
name: "a",
age: 16
},
{
name: "a",
age: 17
},
{
name: "b",
age: 18
}, {
name: "b",
age: 19
}
];
var countA = 1 //count increase for a
var countB = 1 //count increase for b
names_array.forEach(function(obj, index) {
if (obj.name == 'a' && index >= 1) {
obj.name = obj.name + '_' + countA++; //rename a
}
if (obj.name == 'b' && index >= 4) {
obj.name = obj.name + '_' + countB++; //rename b
}
});
console.log(names_array)
You could use a lookup object with key-value pairs of name value and its occurence
const nameValueLookup = {}
const namesArray = [
{ name: "a", age: 15 },
{ name: "a", age: 16 },
{ name: "a", age: 17 },
{ name: "b", age: 18 },
{ name: "b", age: 19 },
]
const res = namesArray.map((obj) => {
if (nameValueLookup[obj.name]) {
return { ...obj, name: `${obj.name}_${nameValueLookup[obj.name]++}` }
} else {
nameValueLookup[obj.name] = 1
return obj
}
})
console.log(res)

JavaScript array map while keeping original elements in the array

I have this array.
const data = [
{ name: "A", age: "12" },
{ name: "B", age: "5" },
{ name: "C", age: "6" }
];
I want to add additional property called key to this array like this.
const data = [
{ name: "A", age: "12", key: "A12" },
{ name: "B", age: "5", key: "B5" },
{ name: "C", age: "6", key: "C6" }
];
I tired this map function and output is not the one I expect. How do I achieve this using JS map function..
const data = [
{ name: "A", age: "12"},
{ name: "B", age: "5"},
{ name: "C", age: "6"}
];
console.log(
"MAP",
data.map(element => (element.key = element.name + element.age))
);
You need to return an object from the map callback:
const data = [
{ name: "A", age: "12"},
{ name: "B", age: "5"},
{ name: "C", age: "6"}
];
console.log(
data.map(({ name, age }) => ({ name, age, key: name + age }))
);
If you wish to mutate the existing objects, then use forEach instead of .map:
const data = [
{ name: "A", age: "12"},
{ name: "B", age: "5"},
{ name: "C", age: "6"}
];
data.forEach((obj) => {
obj.key = obj.name + obj.age;
});
console.log(data);
Return element as well using the comma operator:
const data = [
{ name: "A", age: "12"},
{ name: "B", age: "5"},
{ name: "C", age: "6"}
];
console.log(data.map(element => (element.key = element.name + element.age, element)));
.as-console-wrapper { max-height: 100% !important; top: auto; }
Or just change your map callback to make it simpler with destructuring:
const data = [
{ name: "A", age: "12"},
{ name: "B", age: "5"},
{ name: "C", age: "6"}
];
console.log(data.map(({ name, age }) => ({ name, age, key: name + age})));
.as-console-wrapper { max-height: 100% !important; top: auto; }
There are more than one way to do this and the Array.map is by far the most concise and clean way to do it as already provided. Here are few other methods:
const data = [ { name: "A", age: "12" }, { name: "B", age: "5" }, { name: "C", age: "6" } ];
let from = Array.from(data, ({name, age}) => ({name, age, key: name+age}))
let assign = data.map(({name, age}) => Object.assign({name, age}, {key: name+age}))
console.log('from: ', from)
console.log('assign: ', assign)
If you want to generate a key from all values (assuming all are primitives) you can also do this:
const data = [
{ name: "A", age: "12", city: 'Miami' }, // "key": "A12Miami"
{ name: "B", age: "2", gender: 'M'}, // "key": "B2M"
];
let all = data.map(obj =>
({...obj, ...Object.fromEntries([['key', Object.values(obj).join('')]])}))
console.log(all)
This way you do not have to specify or care about the pop names etc.

lodash filter by name

I'm trying to figure out how to use lodash to filter the following object:
contacts = {
A: [
{ name: "Albert", age: 16 },
{ name: "Arthur", age: 24}
],
B: [
{ name: "Bob", age: 33 }
],
C: [],
D: [],
...
};
I'd like to be able to filter contacts by name (contains) while keeping the same structure, I don't know to tell lodash to look for any objects on the 2nd level.
Any idea how to go about this?
Try this one
const contacts = {
A: [
{ name: "Albert", age: 16 },
{ name: "Arthur", age: 24}
],
B: [
{ name: "Bob", age: 33 },
{ name: "Ahn", age: 20 },
],
C: [],
D: []
};
const obj = {};
Object.keys(contacts).forEach(index => {
obj[index] = contacts[index].filter(person =>
person.name.includes("th"));
});
console.log(obj);
Use map and filter
var nameToSearch = "Bob";
contacts = Object.keys(contacts).map( s => contacts[s].filter( t => t.name == nameToSearch ) );

Categories