Order objects in array based on values of two attributes - javascript

I have an array of N objects and each object has the following fields:
{
id: 'an id',
description: 'a description',
isUser: true/false
}
I need to order that array based on two things:
Firstly, if the description includes either 'dog', 'cat' or 'animal', it should have sooner position in the array.
Secondly, if the value isUser is false, it should also have a sooner position in the array.
I have notice that the sort function doesn't help when you want to prioritize by value of different attributes, so I am wondering what is the best way to do this in Javascript (or Lodash, which I am also using: https://lodash.com/)

You could check if the wanted top string are in the description and move these item to top, as well as false values of isUser.
var array = [{ id: 1, description: 'cat', isUser: false }, { id: 5, description: 'dog', isUser: true }, { id: 6, description: 'flower', isUser: true }, { id: 7, description: 'cat', isUser: true }, { id: 2, description: 'animal', isUser: false }, { id: 3, description: 'tree', isUser: false }, { id: 4, description: 'dog', isUser: false }];
array.sort(function (a, b) {
var top = ['dog', 'cat', 'animal'];
return top.includes(b.description) - top.includes(a.description) || a.isUser - b.isUser;
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

var test = [{
id: 'an id',
description: 'a description dog',
isUser: false
},{
id: 'an id 2',
description: 'a description animal',
isUser: true
},{
id: 'an id 3',
description: 'a description',
isUser: true
},{
id: 'an id 4',
description: 'a description',
isUser: false
}]
function sort(arr){
return arr.sort(a=> !(a.description.includes('dog')||a.description.includes('cat')||a.description.includes('animal') || !a.isUser))
}
console.log(sort(test))

Assuming you question is to rearrange the existing array based on the properties and conditions given.
// grouping on basis of "description"
const animalGrp = _.groupBy(array, (t) => _.includes(t.description, 'dog') || _.includes(t.description, 'cat') || _.includes(t.description, 'animal') );
// grouping on basis of "isUser"
const userGrp = _.groupBy(animalGrp.false, 'isUser');
// final output
const result = [...animalGrp.true, ...userGrp.true, ...userGrp.false]

You can pass a compareFunction to sort method of array, so the sort function should help. Example:
yourArray.sort( function(a, b) {
if ( !a.isUser || a.description == 'animal') return -1;
return 1;
});

Related

Filter array of objects dynamically according to another array of objects

So I am making a filter functionality for React, so I have an array of objects, and based on another array that contains values to filter the array, I need to get the filtered values.
code: the array of objects to apply the filter to:
const citiesData = [
{
id: 1,
name: 'amritsar',
popu: '1200'
},
{
id: 2,
name: 'jalandhar',
popu: '1300'
},
{
id: 3,
name: 'phagwara',
popu: '1200'
},
{
id: 4,
name: 'ludhiana',
popu: '1400'
},
{
id: 5,
name: 'mumbai',
popu: '2000'
},
{
id: 6,
name: 'banglore',
popu: '2000'
},
{
id: 7,
name: 'ohter city 1',
popu: '1500'
},
{
id: 8,
name: 'ohter city 2',
popu: '1500'
},
{
id: 9,
name: 'anohter city 1',
popu: '2200'
},
{
id: 10,
name: 'anohter city 2',
popu: '2200'
},
]
code: filters array based on what I need to apply the conditions:
const filterCity = [
{
filterType: 'name',
filterValue: 'amritsar'
},
{
filterType: 'popu',
filterValue: '1200'
}
]
solutions I've tried:-
code: solution 1:
const filteredList = citiesData.filter(item => {
return filterCity.filter(fItem => item[fItem.filterType] === fItem.filterValue).length
})
code: solution 2:
const filteredList = citiesData.filter(item => {
return filterCity.reduce((acc, val) => {
if(item[val.filterType] === val.filterValue) {
acc = true
}
return acc;
}, false)
})
code: result I'm getting:
[
{ id: 1, name: 'amritsar', popu: '1200' },
{ id: 3, name: 'phagwara', popu: '1200' }
]
it's giving me two objects because according to the filters array I'm searching for the name and popu fields. but the expected result should be:
[ { id: 1, name: 'amritsar', popu: '1200' } ]
because the name and popu is similar in that but in the second object the name is not the same.
I want the code to check all the conditions and then give me the result. right now it's working on the individual filter and individual array item.
so can anyone help me on this!!
so, it should be an AND filter (combining all conditions)?
res = citiesData.filter(d =>
filterCity.every(f => d[f.filterType] === f.filterValue))
for the OR filter (any condition), replace every with some.

Angular search a key in an object and change the value of another key

I have this data below.
I need to be able to search in the objet for the id or name key and then change the 'show' key to a different value.
How example:
Search the data for id value 2 and change the show value to false.
data = [
{
id: 1,
name: 'one',
show: false;
title: 'title1',
data: [
{
id: 1,
description: 'some description'
},
{
id: 2,
description: 'some other description'
}
]
},
{
id: 2,
name: 'two',
show: true;
title: 'title2',
data: [
{
id: 1,
description: 'some description'
},
{
id: 2,
description: 'some other description'
}
]
}
]
How can I do this?
You can use the findIndex method, and then access your array using the found Index and change any property you want, here's some code that match your use case
let index = data.findIndex((x) => x.id == THE_ID_YOU_ARE_LOOKING_FOR);
if(index > -1) {
data[index].show = THE_VALUE_YOU_WANT;
}
You can also use normal array find method.
let item = data.find(x=>x.id===REQUIRED_ID);
if(item) item.show = false

Filter an array of objects upon a value inside an array of objects inside in javascript

I am fetching an array of objects as following :
const data =
[ { id: 0, company: 'nike', items: [{ id: 0, name: 'caret', price: 100}] }
, { id: 1, company: 'adidas', items: [{ id: 1, name: 'mobile phone', price: 300}] }
]
I want to filter that array of objects by checking the value of the property "name" inside the items array if it is "Caret" or not. If yes, I want to return the same array of objects with all its content but filtered. Which means, it will filter out the object whose item's name is not caret. How can I achieve this in javascript?!
I suppose you are looking for that ?
const data =
[{ id: 0, company: 'nike', items: [{ id: 0, name: 'caret', price: 100}]}
,{ id: 1, company: 'adidas', items: [{ id: 1, name: 'mobile phone', price: 300}]}
]
const filterName = (arr, name)=>arr.filter(el=>el.items.some(x=>x.name==name))
onlyCaret = filterName(data,'caret')
console.log( onlyCaret[0].company ) // nike
console.log( onlyCaret ) // row 0 with { ... company: 'nike' ..}
.as-console-wrapper { max-height: 100% !important; top: 0; }
You need to use Array.filter and then loop through your items for a match
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
const data = [
{
id:0,
company: "nike"
items:[
name: "caret",
price:100
]
},
{
id:1,
company: "adidas"
items:[
name: "mobile phone",
price: 300
]
},
]
const filteredCompanies = data.filter((company)=>{
company.items.forEach((item)=>{
if(item.name === "nike") return true
})
})

how to sort array object based on another object

it possible to sort and rearrange an array that looks like this:
items:[{
id: '5',
name: 'wa'
},{
id: '3',
name: 'ads'
},{
id: '1',
name: 'fdf'
}]
to match the arrangement of this object:
Item_sequence: {
"5": {index: 1},
"1": { index: 0 }
}
Here is the output I’m looking for:
items:[{
id: '1',
name: 'fdf'
},{
id: '5',
name: 'wa'
},{
id: '3',
name: 'ads'
}]
You could check if the index is supplied and if not take a lage value for sorting by delta of two items.
var data = { items: [{ id: '5', name: 'wa' }, { id: '3', name: 'ads' }, { id: '1', name: 'fdf' }] },
sequence = { 5: { index: 1 }, 1: { index: 0 } };
data.items.sort(({ id: a }, { id: b }) =>
(a in sequence ? sequence[a].index : Number.MAX_VALUE) -
(b in sequence ? sequence[b].index : Number.MAX_VALUE)
);
console.log(data.items);
.as-console-wrapper { max-height: 100% !important; top: 0; }
JavaScript specifically, First you have to apply loop to your array "items":
`
let newArr = [];
items.map(obj=>{
//obj will be the element of items array, here it is an object.
if(Item_sequence.obj[id] !== undefined) {
/*this condition will be satisfied when id from items array will be present as a
key in Item_sequence array*/
insertAt(newArr, Item_sequence.obj[id] , obj)
}
else{
newArr.push(obj);
}
})
//After checking on whole array here you assign a newArr value to items array.
items=newArr;
Hope that it will help you.

Copy array of objects and make changes without modifying original array

I have an array of objects. I would like to deep copy the array of objects and make some changes to each object. I want to do this without modifying the original array or original objects that were in that array.
This is the way I have done it. However, being new to JavaScript I want to make sure this is a good approach.
Is there a better way to do this?
const users =
[
{
id : 1,
name : 'Jack',
approved : false
},
{
id : 2,
name : 'Bill',
approved : true
},
{
id : 3,
name : 'Rick',
approved : false
},
{
id : 4,
name : 'Rick',
approved : true
}
];
const users2 =
users
.map(
(u) =>
{
return Object.assign({}, u);
}
)
.map(
(u) =>
{
u.approved = true;
return u;
}
);
console.log('New users2 array of objects:')
console.log(users2);
console.log('This was original users array is untouched:')
console.log(users);
Output:
New users2 array of objects:
[ { id: 1, name: 'Jack', approved: true },
{ id: 2, name: 'Bill', approved: true },
{ id: 3, name: 'Rick', approved: true },
{ id: 4, name: 'Rick', approved: true } ]
This was original users array is untouched:
[ { id: 1, name: 'Jack', approved: false },
{ id: 2, name: 'Bill', approved: true },
{ id: 3, name: 'Rick', approved: false },
{ id: 4, name: 'Rick', approved: true } ]
For a single pass, you could use Object.assign with the changed property as well.
const users = [{ id: 1, name: 'Jack', approved: false }, { id: 2, name: 'Bill', approved: true }, { id: 3, name: 'Rick', approved: false }, { id: 4, name: 'Rick', approved: true }];
const users2 = users.map(u => Object.assign({}, u, { approved: true }));
console.log(users2);
console.log(users);
.as-console-wrapper { max-height: 100% !important; top: 0; }
UPDATE with spreading properties.
const users = [{ id: 1, name: 'Jack', approved: false }, { id: 2, name: 'Bill', approved: true }, { id: 3, name: 'Rick', approved: false }, { id: 4, name: 'Rick', approved: true }];
const users2 = users.map(u => ({ ...u, approved: true }));
console.log(users2);
console.log(users);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Yes that looks good. You could also perform the modification when you are cloning, in order to avoid mapping over the array twice.
const users2 = users.map((u) => {
const copiedUser = Object.assign({}, u);
copiedUser.approved = true;
return copiedUser;
});
I prefer JSON.stringify and JSON.parse
var users = [ { id: 1, name: 'Jack', approved: false },
{ id: 2, name: 'Bill', approved: true },
{ id: 3, name: 'Rick', approved: false },
{ id: 4, name: 'Rick', approved: true } ];
// user2 will be copy of array users without reference
var users2 = JSON.parse(JSON.stringify(users));
There are a few ways to copy a array in javascript, i believed that the most used are:
slice()
Array.from()
The slice function will return a portion (or all content) of a given array as a new array, based at a begin and end index (begin and end index are optional):
const a = [1,2,3,4,5,6,7,8,9]
/*
* Only begin index
*/
const b = a.slice(2)
console.log(b) //Will Print [3,4,5,6,7,8,9]
/*
* Begin index and end index
*/
const c = a.slice(5,8)
console.log(c) //Will Print [6,7,8]
/*
* No indexes provided
*/
const d = a.slice()
console.log(d) //Will print [1,2,3,4,5,6,7,8,9]
Array.from() is a function that will create a new array from an array-like or iterable parameters.
const a = Array.from('bar');
console.log(a) //Will Print ["b","a","r"]
const b = ["for","bar"];
const c = Array.from(b);
console.log(c) //Will print ["for","bar"]
More about slice
More about Array.from()
In React JS I tried most ways of copying and modifying the newly copied array but it still modified the original array. The methods I tried are slice Array.from for loop spread operator, all this ended up modifying the original array.
The solution was, stringify the original array and assign it to a new variable, then parse the variable to get a fresh copy without reference as stated by #Roman Yakoviv above.

Categories

Resources