Javascript filter by nested object attribute - javascript

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"; })

Related

Filter array based on other values in that same array

I have an array of data like so:
[
{id: 1, date: "2022-10-01T12:00:00.00", type: 1},
{id: 2, date: "2022-10-02T12:00:00.00", type: 1},
{id: 3, date: "2022-10-03T12:00:00.00", type: 2},
{id: 4, date: "2022-10-04T12:00:00.00", type: 2},
]
I'd like to filter this so that I get an array of objects that only includes objects with the most recent date for each type. So something like this:
[
{id: 2, dttm: "2022-10-02T12:00:00.00", type: 1},
{id: 4, dttm: "2022-10-04T12:00:00.00", type: 2},
]
I suspect there's a clever way to do this with the .reduce() function, but I haven't quite figured that out yet.
It's easy to compare dates this way just using string comparing since they are sorted by year-month-date. As for the rest, yes reduce is an option but basically it's just a loop over the array grouping by type.
var arr = [
{id: 1, date: "2022-10-01T12:00:00.00", type: 1},
{id: 2, date: "2022-10-02T12:00:00.00", type: 1},
{id: 3, date: "2022-10-03T12:00:00.00", type: 2},
{id: 4, date: "2022-10-04T12:00:00.00", type: 2},
];
var grouped = arr.reduce(function(agg, item) {
agg[item.type] = agg[item.type] || {
id: item.id,
dttm: item.date,
type: item.type
};
if (item.date > agg[item.type].dttm) {
agg[item.type].id = item.id
agg[item.type].dttm = item.date
}
return agg;
}, {})
console.log (Object.values(grouped))
We can achieve this using .reduce by keeping a running tally of the most recent items.
Note:
Dates can be compared in js as their valueOf method is equivalent to someDate.getTime() which gives a nice integer for comparison.
let items = [{
id: 1,
date: "2022-10-01T12:00:00.00",
type: 1
},
{
id: 2,
date: "2022-10-02T12:00:00.00",
type: 1
},
{
id: 3,
date: "2022-10-03T12:00:00.00",
type: 2
},
{
id: 4,
date: "2022-10-04T12:00:00.00",
type: 2
},
]
let recentItems = Object.values(items.reduce((recent, item) => {
debugger;
if (
// type has not items yet
!recent[item.type]
// the current item is more recent
||
new Date(recent[item.type].date) < new Date(item.date)
) {
recent[item.type] = item
}
return recent;
}, {}))
console.log(recentItems)
This does what you specify. (See in-code comments for more info.)
// Calls filter function on the data array and prints output
const data = getData();
console.log(recentOfEachType(data));
// Defines filter function
function recentOfEachType(arr){
// Sets up output array
let recents = [];
// Loops through data to populate output
for(const item of arr){
// Gets position of existing item with this type
const typeIndex = recents.findIndex(recent => recent.type === item.type);
// If no item with this type has been added yet
if(typeIndex < 0){
recents.push(item);
}
// If a newer item is found (ignoring items with identical timestamps)
else if(item.date > recents[typeIndex].date){
recents[typeIndex] = item;
}
// (else do nothing)
}
return recents;
}
// Creates oringal data array
function getData(){
return [
{id: 1, date: "2022-10-01T12:00:00.00", type: 1},
{id: 2, date: "2022-10-02T12:00:00.00", type: 1},
{id: 3, date: "2022-10-03T12:00:00.00", type: 2},
{id: 4, date: "2022-10-04T12:00:00.00", type: 2}
];
}

Sorting array of objects based on two attributes [duplicate]

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']);

Delete multiple objects in an array by id

I have a main array of objects with each object having some key/values as well as a "id" key with 1,2,3,4,5, etc
Now I have another array representing just id's (like [2,3])
I want to use this array to delete objects from the main array...so in this case, objects from the main array having id's 2 & 3 should be deleted
While I am aware of findBy(id), I am not sure if that can be used to delete multiple objects at once.
You can use filter. In the filter callback function check if the id is also there in id array by using includes
let idArr = [1, 2]
let obj = [{
id: 1,
name: 'abc'
},
{
id: 2,
name: 'abc'
},
{
id: 3,
name: 'abc'
},
{
id: 4,
name: 'abc'
}
];
let data = obj.filter(item => !idArr.includes(item.id));
console.log(data);
console.log(obj)
using filter might work well here. you could write something like:
var newArray = oldArray.filter(object => !ids.includes(object.id))
You can do it, like this:
[2,3].forEach(key => {
delete object[key];
})
You can use filter method for this.
Ex:
let id = 2;
let list = [{
Id: 1,
Name: 'a'
}, {
Id: 2,
Name: 'b'
}, {
Id: 3,
Name: 'c'
}];
let lists = list.filter(x => {
return x.Id != id;
})
console.log(lists);
Assuming you want to delete items from the original array by entirely removing the element from the array (and you don't want to get a new array), you can take advantage of
Array.splice
let idArr = [1, 2];
let obj = [{
id: 1
},
{
id: 2
},
{
id: 3
},
{
id: 4
}
];
for (let id of idArr) {
// look for the element by its id.
const objIdRef = obj.find(i => i.id === id);
// if it actually exists, splice it.
objIdRef && obj.splice(obj.indexOf(objIdRef), 1);
}
console.log(obj);
If the obj array is big, you might want to make a map from it before processing the id array, so that the complexing is reduced to O(1) when the delete process begins.
Perhaps This is what you want:
var arr= [{id:1, name: "foo"}, {id:2, name: "bar"}, {id:3, name:"not to be deleted"}];
var idsToDelete = [1, 2];
var res = arr.map((i, idx)=>{
return arr[idx] = idsToDelete.includes(i.id)? undefined : arr[idx]
}).filter(i=>i)
console.log(res)
You can try Lodash.js functions _.forEach() and _.remove()
let valuesArr = [
{id: 1, name: "dog"},
{id: 2, name: "cat"},
{id: 3, name: "rat"},
{id: 4, name: "bat"},
{id: 5, name: "pig"},
];
let removeValFromIndex = [
{id: 2, name: "cat"},
{id: 5, name: "pig"},
];
_.forEach(removeValFromIndex, (indi) => {
_.remove(valuesArr, (item) => {
return item.id === indi.id;
});
})
console.log(valuesArr)
/*[
{id: 1, name: "dog"},
{id: 3, name: "rat"},
{id: 4, name: "bat"},
]; */
Don't forget to clone (_.clone(valuesArr) or [...valuesArr]) before mutate your array

How can I remove the name field from a json array?

I have a json array like this:
(3) [{…}, {…}, {…}]
0: {Id: 1, Name: "bask"}
1: {Id: 2, Name: "voll"}
2: {Id: 3, Name: "badminton"}
I want to turn it into something like this:
{1:"bask",2:"voll",3:"badminton"}
You can use reduce to loop through array and build a object of desired key/value pair
let data = [{Id: 1, Name: "bask"},{Id: 2, Name: "voll"},{Id: 3, Name: "badminton"}]
let output = data.reduce((op, {Id, Name}) => {
op[Id] = Name
return op
},{})
console.log(output)
You could take Object.fromEntries with the maped key/value pairs.
var array = [{ Id: 1, Name: "bask" }, { Id: 2, Name: "voll" }, { Id: 3, Name: "badminton" }],
object = Object.fromEntries(array.map(({ Id, Name }) => [Id, Name]));
console.log(object);
You can check out the reduce() function!
let array = [
{Id: 1, Name: "bask"},
{Id: 2, Name: "voll"},
{Id: 3, Name: "badminton"}
];
console.log(_.reduce(array, function(result, obj){
result[obj.Id] = obj.Name;
return result;
}, {}));
You can checkout lodash an awesome library with many other such utilities!
You can do this with reduce():
var a = [
{Id: 1, Name: "bask"},
{Id: 2, Name: "voll"},
{Id: 3, Name: "badminton"}
]
b = a.reduce((acc, item) => {
acc[item.Id] = item.Name;
return acc;
}
console.log(b);
You can do it in different ways, here one of them.
let dataArray = [
{id: 1, name: 'bask'},
{id: 2, name: 'voll'},
{id: 3, name: 'badminton'}
]
let ouputObject = {}
dataArray.map(data => {
ouputObject[`${data.id}`] = data.name
})
console.log(ouputObject)
outputObject will be
Object {
1: "bask",
2: "voll",
3: "badminton"
}
Using Array.reduce() :
var arr = [{
Id: 1,
Name: "bask"
}, {
Id: 2,
Name: "voll"
}, {
Id: 3,
Name: "badminton"
}];
var reduceObj = arr.reduce(function(result, currentElement) {
result[currentElement.Id] = currentElement.Name;
return result;
}, {});
console.log(reduceObj);
Using Array.map() :
var arr = [{
Id: 1,
Name: "bask"
}, {
Id: 2,
Name: "voll"
}, {
Id: 3,
Name: "badminton"
}];
var mapObject = {}
arr.map(obj => {
mapObject[obj.Id] = obj.Name
})
console.log(mapObject);

Check if a value exists in an Array object in JavaScript or Angular

I want to check if a value exist in an array object. Example:
I have this array:
[
{id: 1, name: 'foo'},
{id: 2, name: 'bar'},
{id: 3, name: 'test'}
]
And I want check if id = 2 exists here.
You can use Array.prototype.some
var a = [
{id: 1, name: 'foo'},
{id: 2, name: 'bar'},
{id: 3, name: 'test'}
];
var isPresent = a.some(function(el){ return el.id === 2});
console.log(isPresent);
You can use some().
If you want to just check whether a certain value exists or not, the Array.some() method (since JavaScript 1.6) is fair enough as already mentioned.
let a = [
{id: 1, name: 'foo'},
{id: 2, name: 'bar'},
{id: 3, name: 'test'}
];
let isPresent = a.some(function(el){ return el.id === 2});
console.log(isPresent);
Also, find() is a possible choice.
If you want to fetch the entire very first object whose certain key has a specific value, it is better to use the Array.find() method which has been present since ES6.
let hasPresentOn = a.find(
function(el) {
return el.id === 2
}
);
console.log(hasPresentOn);
You can use the find method as below:
var x=[
{id: 1, name: 'foo'},
{id: 2, name: 'bar'},
{id: 3, name: 'test'}
]
var target=x.find(temp=>temp.id==2)
if(target)
console.log(target)
else
console.log("doesn't exists")
Try this:
let idx = array.findIndex(elem => elem.id === 2)
if (idx !== -1){
// Your element exists
}

Categories

Resources