Sorting array of objects based on two attributes [duplicate] - javascript

This question already has answers here:
How to sort an array of objects by multiple fields?
(38 answers)
Closed 1 year ago.
I want to sort Below array based on name and is_closed.
this.rawDataListDup = [
{id: 1, name: 'john','is_closed':true},
{id: 2, name: 'james','is_closed':true},
{id: 3, name: 'jane','is_closed':false},
{id: 4, name: 'alex','is_closed':false},
{id: 5, name: 'david','is_closed':true},
];
As of now i can only sort using any one of the attribute using below code.
let colName = 'name'
this.rawDataListDup.sort((b, a) => a[colName] < b[colName] ? 1 : a[colName] > b[colName] ? -1 : 0)
I want array objects with is_closed = false on top of array and also it should be in Alphabetical order. like this
this.rawDataListDup = [
{id: 4, name: 'alex','is_closed':false},
{id: 3, name: 'jane','is_closed':false},
{id: 5, name: 'david','is_closed':true},
{id: 2, name: 'james','is_closed':true},
{id: 1, name: 'john','is_closed':true},
];
how to do this?

You can do this with sort with multiple conditions inside sort:
const rawDataListDup = [
{id: 1, name: 'john','is_closed':true},
{id: 2, name: 'james','is_closed':true},
{id: 3, name: 'jane','is_closed':false},
{id: 4, name: 'alex','is_closed':false},
{id: 5, name: 'david','is_closed':true},
];
const sortedList = rawDataListDup.sort((a,b)=>(a.is_closed-b.is_closed) || a.name.localeCompare(b.name));
console.log(sortedList);

It just write simple code.
const rawDataListDup = [
{id: 1, name: 'john','is_closed':true},
{id: 2, name: 'james','is_closed':true},
{id: 3, name: 'jane','is_closed':false},
{id: 4, name: 'alex','is_closed':false},
{id: 5, name: 'david','is_closed':true},
];
rawDataListDup.sort(function(a, b) {
return a.is_closed - b.is_closed || a.name - b.name;
});
//OR
var obj = rawDataListDup.sort((a, b) => a.is_closed - b.is_closed || a.name - b.name);

You could also use lodash (sortBy).
Example:
_.sortBy(rawDataListDup, ['is_closed', 'name']);

Related

Delete objects from the array of object which reference id did not matches with any other object id from the same array of objects in javascript

I want to delete those objectσ which refId id that dont match with any id of array of object, if refId is null dont delete it
[
{id: 1 , refId:null, name:'jhon'},
{id: 2 , refId:null, name:'sam'},
{id: 3 , refId:1, name:'fam'},
{id: 4 , refId:2, name:'jam'},
{id: 5 , refId:16, name:'ram'},
{id: 6 , refId:15, name:'nam'}
]
result: should b:
[
{id: 1 , refId:null, name:'jhon'},
{id: 2 , refId:null, name:'sam'},
{id: 3 , refId:1, name:'fam'},
{id: 4 , refId:2, name:'jam'},
]
Please try once with following code:
const arr1 = [
{ id: 1, refId: null, name: "jhon" },
{ id: 2, refId: null, name: "sam" },
{ id: 3, refId: 1, name: "fam" },
{ id: 4, refId: 2, name: "jam" },
{ id: 5, refId: 16, name: "ram" },
{ id: 6, refId: 15, name: "nam" },
];
console.log(
arr1.filter((obj) => {
return obj.refId === null || arr1.some((o) => o.id === obj.refId);
})
);
What you have here is a tree structure, if the tree is small using a filter or some is fine, but if the tree is large you should try doing it with a mapping(dictionary).
let nodes = [
{id: 1 , refId:null, name:'jhon'},
{id: 2 , refId:null, name:'sam'},
{id: 3 , refId:1, name:'fam'},
{id: 4 , refId:2, name:'jam'},
{id: 5 , refId:16, name:'ram'},
{id: 6 , refId:15, name:'nam'}
]
let dictionary = nodes.reduce((dic, node) => { dic[node.id] = true; return dic; }, { [null]: true });
let result = nodes.filter((node) => dictionary[node.refId]);
console.log(result);

Why do these matching results fail to satisfy the conditions of the if/else statement? [duplicate]

This question already has answers here:
Object comparison in JavaScript [duplicate]
(10 answers)
Closed 1 year ago.
On line 9, collection[2] does equal source, but the resulting if statement logs 'sorry not found'. Why doesn't it log Object.keys(source) instead?
const collection = [
{id: 1, name: 'A'},
{id: 2, name: 'B'},
{id: 3, name: 'C'}
]
const source = {id: 3, name: 'C'}
if (collection[2] == source) {
console.log(Object.keys(source))
} else {
console.log('sorry not found')
}
Objects are reference types so you can’t just use === or == to compare 2 objects. Instead try this:
const collection = [
{id: 1, name: 'A'},
{id: 2, name: 'B'},
{id: 3, name: 'C'}
]
const source = {id: 3, name: 'C'}
if (JSON.stringify(collection[2]) === JSON.stringify(source)) {
console.log(Object.keys(source))
} else {
console.log('sorry not found')
}

Javascript filter by nested object attribute

I have the following array:
arr = [{id: 1, type: {name: "Approval", id: 1}},
{id: 2, type: {name: "Rejection", id: 2}},
{id: 3, type: {name: "Approval", id: 1}}
];
Why does the following produce and [] result? I would expect to get an array of 2 objects (i.e. id 1 and 3).
$.grep(arr, function(a) { return a.type.name === "Approval"; })
Thoughts?
Why do you use jQuery here? Javascript gives you perfect methods for that. filter or find.
const arr = [
{id: 1, type: {name: "Approval", id: 1}},
{id: 2, type: {name: "Rejection", id: 2}},
{id: 3, type: {name: "Approval", id: 1}}
];
const matches = arr
.filter(entry => entry.type.name === 'Approval')
console.log(matches)
return is a reserved keyword in js. Hence you cannot use it as a variable and access its properties.
Instead, you need to access the properties of the a variable:
$.grep(arr, function(a) { return a.type.name === "Approval"; })

Why does map function return undefined but console.log logs out?

I want to return matching proprieties of two arrays of objects. But I got undefined from map function.
let fruits1 = [
{id: 1, name: "apple"},
{id: 2, name: "dragon fruit"},
{id: 3, name: "banana"},
{id: 4, name: "kiwi"},
{id: 5, name: "pineapple"},
{id: 6, name: "watermelon"},
{id: 7, name: "pear"},
]
let fruits2 = [
{id: 7, name: "pear"},
{id: 10, name: "avocado"},
{id: 5, name: "pineapple"},
]
fruits1.forEach((fruit1) => {
fruits2.filter((fruit2) => {
return fruit1.name === fruit2.name;
}).map((newFruit) => {
//console.log(newFruit.name);
return newFruit.name;
})
})
What are you looking for is an array intersection:
// Generic helper function that can be used for the three operations:
const operation = (list1, list2, isUnion = false) =>
list1.filter( a => isUnion === list2.some( b => a.name === b.name ) );
// Following functions are to be used:
const inBoth = (list1, list2) => operation(list1, list2, true),
inFirstOnly = operation,
inSecondOnly = (list1, list2) => inFirstOnly(list2, list1);
Usage:
console.log('inBoth:', inBoth(list1, list2));
Working Example:
// Generic helper function that can be used for the three operations:
const operation = (list1, list2, isUnion = false) =>
list1.filter( a => isUnion === list2.some( b => a.name === b.name ) );
// Following functions are to be used:
const inBoth = (list1, list2) => operation(list1, list2, true),
inFirstOnly = operation,
inSecondOnly = (list1, list2) => inFirstOnly(list2, list1);
let fruits1 = [
{id: 1, name: "apple"},
{id: 2, name: "dragon fruit"},
{id: 3, name: "banana"},
{id: 4, name: "kiwi"},
{id: 5, name: "pineapple"},
{id: 6, name: "watermelon"},
{id: 7, name: "pear"},
]
let fruits2 = [
{id: 7, name: "pear"},
{id: 10, name: "avocado"},
{id: 5, name: "pineapple"},
]
console.log('inBoth:', inBoth(fruits1, fruits2));
You could use a Set and filter the names.
const names = ({ name }) => name;
var fruits1 = [{ id: 1, name: "apple" }, { id: 2, name: "dragon fruit" }, { id: 3, name: "banana" }, { id: 4, name: "kiwi" }, { id: 5, name: "pineapple" }, { id: 6, name: "watermelon" }, { id: 7, name: "pear" }],
fruits2 = [{ id: 7, name: "pear" }, { id: 10, name: "avocado" }, { id: 5, name: "pineapple" }],
common = fruits1
.map(names)
.filter(Set.prototype.has, new Set(fruits2.map(names)));
console.log(common);
What you want to do is this:
/* first we filter fruits1 (arbitrary) */
let matchingFruits = fruits1.filter(f1 => {
/* then we filter the frut if it exists in frtuis2 */
return fruits2.find(f2 => f2.name === f1.name)
}).map(fruit => fruit.name) // and now we map if we only want the name strings
If you're not using a polyfill Array.find will not work in IE. The alternative would be using Array.indexOf (thanks for pointing this out #JakobE).
Be aware that Array.forEach return value is undefined and that, in order to actually use the Array.map correctly, one has to consume the returned value somehow or assign it to a variable, as we just did with matchingFruits.

JavaScript Update multiple object properties

I have this code below that finds the index of specific object using findIndex method and Update object's name property. Is there anyway i can update mutiple object's name property? E.g.
var rofl = ["0"];
// Instead of ["0"] how do i update multiple object by putting var rofl = ["1","2","3"];
let myArray = [
{id: 0, name: "Jhon"},
{id: 1, name: "Sara"},
{id: 2, name: "Domnic"},
{id: 3, name: "Bravo"}
],
objIndex = myArray.findIndex((obj => obj.id == rofl));
console.log("Before update: ", myArray[objIndex]) // {id: 0, name: "Jhon"}
myArray[objIndex].name = ("Jerry");
console.log("After update: ", myArray[objIndex]) // {id: 0, name: "Jerry"}
Use forEach instead:
const myArray = [
{id: 0, name: "Jhon"},
{id: 1, name: "Sara"},
{id: 2, name: "Domnic"},
{id: 3, name: "Bravo"}
];
["1","2","3"].forEach(findId =>
myArray.find(({ id }) => id == findId).name = 'Jerry'
);
console.log(myArray);
If the IDs have a chance of not existing in the array, you'll have to add a test for that as well:
const myArray = [
{id: 0, name: "Jhon"},
{id: 1, name: "Sara"},
{id: 2, name: "Domnic"},
{id: 3, name: "Bravo"}
];
["1","2","3", "10"].forEach(findId => {
const foundObj = myArray.find(({ id }) => id == findId);
if (foundObj) foundObj.name = 'Jerry';
});
console.log(myArray);
Use Array.forEach
let myArray = [{id: 0, name: "Jhon"},{id: 1, name: "Sara"},{id: 2, name: "Domnic"},{id: 3, name: "Bravo"}];
let rofl = ["1","2","3"];
myArray.forEach((obj) => {if(rofl.includes(obj.id.toString())) obj.name = 'Jerry'})
console.log(myArray);

Categories

Resources