Fetching Objects from Array by passing key & value in javascript - javascript

This is my Array of objects. I want to filter the objects by passing query in a function.
const products = [{
name: "A",
color: "Blue",
size: 50
},
{
name: "B",
color: "Blue",
size: 60
},
{
name: "C",
color: "Black",
size: 70
},
{
name: "D",
color: "Green",
size: 50
}
];
My desired output which will filter from the query which I am passing in function which can be anything
{
name: "A",
color: "Blue",
size: 50
}, {
name: "C",
color: "Black",
size: 70
}
This is my query object which I will pass to function
const filter = {
color: ["Blue", "Black"],
size: [70, 50]
};
This is my function which I can assign to other variable and use it for further operations
const filteredData = filterIt(products, filter);

Here is another option:
function filterIt(products, filter) {
return products.filter(p => {
for (const k in filter) {
if (filter[k].indexOf(p[k]) === -1) {
return false;
}
}
return true;
})
}
See a Demo
If you want to make an OR instead of an AND in the logic the previous function modified would be:
function filterIt(products, filter) {
return products.filter(p => {
for (const k in filter) {
// if a value of any property of the product is contained in a filter array, include it
if (filter[k].indexOf(p[k]) !== -1) {
return true;
}
}
return false;
})
}
See a Demo for this one too :)

You could get the entries of the filter object and take key and value for checking with includes.
const
filterBy = filter => o => Object.entries(filter).every(([k, v]) => v.includes(o[k])),
filterIt = (array, filter) => array.filter(filterBy(filter)),
products = [{ name: "A", color: "Blue", size: 50 }, { name: "B", color: "Blue", size: 60 }, { name: "C", color: "Black", size: 70 }, { name: "D", color: "Green", size: 50 }],
filter = { color: ["Blue", "Black"], size: [70, 50] },
filteredData = filterIt(products, filter);
console.log(filteredData);
.as-console-wrapper { max-height: 100% !important; top: 0; }

const products = [{
name: "A",
color: "Blue",
size: 50
},
{
name: "B",
color: "Blue",
size: 60
},
{
name: "C",
color: "Black",
size: 70
},
{
name: "D",
color: "Green",
size: 50
}
];
const filter = {
color: ["Blue", "Black"],
size: [70, 50]
};
let filterIt = (products, filter) => {
return products.filter(p => {
//get all filter keys
let keys = Object.keys(filter);
let validkeys = [];
keys.forEach(k=>{
// check if filter property exist and includes filter value
if(p.hasOwnProperty(k) && filter[k].includes(p[k])){
validkeys.push(true);
}
})
//check all filter matches
return validkeys.length === keys.length;
});
}
const filteredData = filterIt(products, filter);
console.log("...filteredData", filteredData);

Related

How to Filter a Nested Object with array of String

let products = [
{
name: "A",
color: "Blue",
size: {
size1: 1,
size2: 2,
size3: 3,
},
},
{
name: "B",
color: "Blue",
size: {
size1: 5,
size2: 19,
size3: 22,
},
},
{ name: "C", color: "Black", size: 70 },
{ name: "D", color: "Green", size: 50 },
];
filters = ['Blue','2'];
the result must be the object that checks all strings in the array for example
{
name: "A",
color: "Blue",
size: {
size1: 1,
size2: 2,
size3: 3,
},
},
the research must be accepted whatever the value in the
You can resolve the nest via using a stack in some manner, either by recursion or iteratively using a stack explicitly. Here's a recursive solution:
function getFiltered(obj, filters, found = null) {
let outermostCall = (found === null);
if (outermostCall) { //outermost call
found = [];
for (let index = 0; index < filters.length; index++) {
found[index] = false;
}
}
for (let key in obj) {
if (typeof obj[key] === 'object') {
let tempFound = getFiltered(obj[key], filters, found);
for (let index = 0; index < found.length; index++) {
if (tempFound[index]) found[index] = true;
}
} else {
let foundIndex = -1;
for (let index = 0; index < filters.length; index++) {
if (filters[index] == obj[key]) {
foundIndex = index;
index = filters.length;
}
}
if (foundIndex >= 0) {
found[foundIndex] = true;
}
}
}
if (outermostCall) {
return !found.filter(item => !item).length;
}
return found;
}
function getAllFiltered(array, filters) {
let output = [];
for (let obj of array) {
if (getFiltered(obj, filters)) output.push(obj);
}
return output;
}
let products = [
{
name: "A",
color: "Blue",
size: {
size1: 1,
size2: 2,
size3: 3,
},
},
{
name: "B",
color: "Blue",
size: {
size1: 5,
size2: 19,
size3: 22,
},
},
{ name: "C", color: "Black", size: 70 },
{ name: "D", color: "Green", size: 50 },
];
let filters = ['Blue','2'];
console.log(getAllFiltered(products, filters));
You could take a closure over any of the search values and check if all of them are in the object or nested objest for filtering.
const
has = f => {
const check = o => o && typeof o === 'object'
? Object.values(o).some(check)
: f === o;
return check;
},
products = [{ name: "A", color: "Blue", size: { size1: 1, size2: 2, size3: 3 } }, { name: "B", color: "Blue", size: { size1: 5, size2: 19, size3: 22 } }, { name: "C", color: "Black", size: 70 }, { name: "D", color: "Green", size: 50 }],
search = ['Blue', 2],
result = products.filter(o => search.every(f => has(f)(o)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use Array.every to check if all the filters are present in the object, if that's what you mean.
const products = [
{ name: "A", color: "Blue", size: { size1:1, size2:2, size3:3 } },
{ name: "B", color: "Blue", size: { size1:5, size2:19, size3:22 } },
{ name: "C", color: "Black", size: 70 },
{ name: "D", color: "Green", size: 50 },
];
const filters = ['Blue','2'];
const filtered = products.filter(product => {
return Object.values(product).every(value => {
return filters.includes(value);
});
});
console.log(filtered);
The function strings returns all nested strings within an object, converting any numbers to strings. Then, we just filter any product where the list of strings includes all necessary matches.
const products = [{"name":"A","color":"Blue","size":{"size1":1,"size2":2,"size3":3}},{"name":"B","color":"Blue","size":{"size1":5,"size2":19,"size3":22}},{"name":"C","color":"Black","size":70},{"name":"D","color":"Green","size":50}];
const filters = ['Blue','2'];
const subsetMatch=(a,s)=>s.every(i=>a.includes(i));
const strings=i=>typeof i==='object'?Object.values(i).flatMap(strings):i+'';
console.log(products.filter(i=>subsetMatch(strings(i),filters)));

How to order an object based on the given values in javascript [duplicate]

I would like to get your help about this little problem.
I have like to order this array depending on the code value but not in alphabetical order.
(I specified this in bold but got eventually flagged anyway, people don't even care about reading the question)
For example I would like to have all the green objects, then all the blue ones and then all the red ones. What is the best way to do that?
[
{ code: "RED", value: 0},
{ code: "BLUE", value: 0},
{ code: "RED", value: 0},
{ code: "GREEN", value: 0},
{ code: "BLUE", value: 0},
{ code: "RED", value: 0},
{ code: "GREEN", value: 0},
{ code: "BLUE", value: 0}
]
Is it possible to do that with the sort function? What would the condition be in that case?
You could take an object for the wanted order.
var array = [{ code: "RED", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }],
order = { GREEN: 1, BLUE: 2, RED: 3 };
array.sort(function (a, b) {
return order[a.code] - order[b.code];
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For unknow colors/values, you could use a default value with
0, for sorting to top or
Infinity or as some suggest because of the ability for caculating Number.MAX_VALUE for sorting to the end,
or any other value for sorting inbetween the other groups.
At last you could sort the special treated items with an other sorting part, chained with logical OR ||.
var array = [{ code: "YELLOW", value: 0 }, { code: "BLACK", value: 0 }, { code: "RED", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }],
order = { GREEN: 1, BLUE: 2, RED: 3, default: Infinity };
array.sort(function (a, b) {
return (order[a.code] || order.default) - (order[b.code] || order.default) || a.code.localeCompare(b.code);
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Set the custom priority first
var codePriority = [ "GREEN", "BLUE", "RED" ];
Now use the same in sorting as
arr.sort( function(a,b){
if ( a.code == b.code ) return a.value - b.value;
return codePriority.indexOf( a.code ) - codePriority.indexOf( b.code ) ; notice this line
})
Demo
var arr = [
{ code: "RED", value: 0},
{ code: "BLUE", value: 0},
{ code: "RED", value: 0},
{ code: "GREEN", value: 0},
{ code: "BLUE", value: 0},
{ code: "RED", value: 0},
{ code: "GREEN", value: 0},
{ code: "BLUE", value: 0}
];
var codePriority = [ "GREEN", "BLUE", "RED" ];
arr.sort( function(a,b){
if ( a.code == b.code ) return a.value - b.value;
return codePriority.indexOf( a.code ) - codePriority.indexOf( b.code )
});
console.log( arr );
You could implement a schema array and sort according to element's index inside that schema array.
const a = ['GREEN', 'BLUE', 'RED'];
const o = [{code:"RED",value:0},{code:"BLUE",value:0},{code:"RED",value:0},{code:"GREEN",value:0},{code:"BLUE",value:0},{code:"RED",value:0},{code:"GREEN",value:0},{code:"BLUE",value:0}];
const r = o.slice().sort(({ code: q }, { code: w }) => a.indexOf(q) - a.indexOf(w));
console.log(r);
this is a function for sorting by a specific color.
const colors = [{
name: "T-shirt",
color: "red",
price: 20
},
{
name: "Shoes",
color: "yellow",
price: 20
},
{
name: "Pants",
color: "red",
price: 20
},
{
name: "Cap",
color: "yellow",
price: 20
},
{
name: "Skirt",
color: "red",
price: 15
},
]
let sortByColor = color => colors.sort((a, b) => a.color === color ? -1 : 1)
console.log(sortByColor('red'))
You can use the sort function i.e Array.prototype.sort() Visit https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Firstly you have to decide whether you want to sort in ascending order or in descending order.
To sort in ascending order you can do something like this:
arr.sort((a, b) => {
return a.color < b.color ? -1 : a.color > b.color ? 1 : 0;
});
An to do it in descending order:
arr.sort((a, b) => {
return a.color > b.color ? -1 : a.color < b.color ? 1 : 0;
});
Now suppose you want a certain color sorted and displayed first. You can have a function like this:
const sortByKeyAsc = (arr,color) =>
arr.sort((a, b) => {
if(a.color < b.color || (a.color === color && b.color !== color)){
return -1;
}
if(a.color > b.color || (a.color !== color && b.color === color)){
return 1
}
return 0;
});
and you can use it like this:
const array1 = sortByKeyAsc(arr,'pink');
I was dealing with a case where I had to match a string status and sort by the various statuses specifically. .findIndex and .includes ended up being the best approach.
statusPriority sets the intended order. Once the indexes are found they can be compared and returned to the .sort
let records = [
{status: 'Record is ready to submit.', active: true, name: 'A'},
{status: 'Record has been sent.', active: true, name: 'B'},
{status: 'Activation is required.', active: true, name: 'C'},
{status: 'Record submission failed.', active: true, name: 'D'},
{status: 'Creation is pending.', active: true, name: 'E'},
]
console.log(records.map(r => r.status))
let statusPriority = ['creation', 'activation', 'sent', 'ready', 'failed'];
records.sort((a, b) => {
let aIndex = statusPriority.findIndex(status => a.status.toLowerCase().includes(status));
let bIndex = statusPriority.findIndex(status => b.status.toLowerCase().includes(status));
return aIndex - bIndex;
})
console.log(records.map(r => r.status))
You can sort color alphabetically by using this function
var sortedArr = arr.sort((first, second)=>{
return first.color < second.color ? -1 : 1
})

Sort by multiple strings in Array using Javascript

I am trying to sort an array by multiple strings but coming up short. Is this possible or is writing something below the only to achieve this?
Doesn't work:
const colorArr = ["Red", "Blue", "Green"]
const colorMap = colorArr.map((a) => a);
const newArr = data.sort((a, b) => {
return (
(a.credits.credit.value !== colorMap) - (b.credits.credit.value !== colorMap)
);
});
console.log("newArr========", newArr)
This works, but can get very lengthy the more conditions...
const data = [
{
credits: {
credit: {
value: "Red",
},
},
},
{
credits: {
credit: {
value: "Blue",
},
},
},
{
credits: {
credit: {
value: "Green",
},
},
},
{
credits: {
credit: {
value: "Red",
},
},
},
{
credits: {
credit: {
value: "Red",
},
},
},
{
credits: {
credit: {
value: "Blue",
},
},
},
];
const nameActor = "Red";
const nameEp = "Blue";
const nameDirector = "Green";
const newArr = data.sort((a, b) => {
return (
(a.credits.credit.value !== nameActor) - (b.credits.credit.value !== nameActor) ||
(a.credits.credit.value !== nameEp) - (b.credits.credit.value !== nameEp) ||
(a.credits.credit.value !== nameDirector) - (b.credits.credit.value !== nameDirector)
);
});
const colorOrder = ['Red', 'Blue', 'Green'];
const order = data.sort(
(a, b) =>
colorOrder.indexOf(a.credits.credit.value) -
colorOrder.indexOf(b.credits.credit.value)
);

Javascript - Concat/update arrays of dictionaries based on key-value

I have two arrays of dictionaries, each having a varied number of objects
Array 1
[
{ id: "1", color: "orange" },
{ id: "2", color: "red" },
]
Array 2
[
{ id: "1", color: "pink" },
{ id: "3", color: "yellow" },
{ id: "4", color: "blue" },
]
I want the two to be combined so that objects with new ids from Array2 are added to Array1 (e.g. id=3,4) and objects with existing keys are replaced (e.g. id=1). So the final output would be
[
{ id: "1", color: "pink" },
{ id: "2", color: "red" },
{ id: "3", color: "yellow" },
{ id: "4", color: "blue" },
]
The only thing I can think of doing is running nested for loops - which is probably the worst way to approach this. What would be the most effective way to achieve this? Thank you.
You can merge those array then filter out the records having duplicate ids and then sort it. I suppose this is what you need:
var arr2=[{"id":"1","color":"pink"}, {"id":"3","color":"yellow"},{"id":"4","color":"blue"}];
var arr1=[{"id":"1","color":"orange"}, {"id":"2","color":"red"}];
var result = [...arr2,...arr1].filter((val, i, self)=>self.findIndex(k=>k.id==val.id)==i).sort((a,b)=>a.id-b.id);
console.log(result);
One approach could be this as well(by using Map):
var arr2=[{"id":"1","color":"pink"}, {"id":"3","color":"yellow"},{"id":"4","color":"blue"}];
var arr1=[{"id":"1","color":"orange"}, {"id":"2","color":"red"}];
var result = [...new Map([...arr1,...arr2].map(k=>[k.id,k])).values()];
console.log(result);
concat, reduce, and values
var a = [
{ id: "1", color: "orange" },
{ id: "2", color: "red" },
]
var b = [
{ id: "1", color: "pink" },
{ id: "3", color: "yellow" },
{ id: "4", color: "blue" },
]
var result = Object.values(a.concat(b).reduce((o, item) => (o[item.id] = item, o), {}))
console.log(result)
I'd say a simple for..loop is much better for this.
var arr1 = [
{ id: "1", color: "orange" },
{ id: "2", color: "red" },
]
var arr2 = [
{ id: "1", color: "pink" },
{ id: "3", color: "yellow" },
{ id: "4", color: "blue" },
]
var ids = arr2.map(i => i.id);
for(let i of arr1){
if(!ids.includes(i.id)){
arr2.push(i)
}
}
console.log(arr2)
Push elements from array, then filter by id and sort by id
for(let obj of arr1){
arr2.push(obj);
}
var newArr = arr2.filter((x, index, self) =>
index === self.findIndex((t) => (
t.id === x.id))); //Filter by id
function compare(a, b) {
if ( a.id < b.id ){
return -1;
}
if ( a.id > b.id ){
return 1;
}
return 0;
}
var output = newArr.sort(compare); // Sort by id
console.log(output);

Sort an array of object by a property (with custom order, not alphabetically)

I would like to get your help about this little problem.
I have like to order this array depending on the code value but not in alphabetical order.
(I specified this in bold but got eventually flagged anyway, people don't even care about reading the question)
For example I would like to have all the green objects, then all the blue ones and then all the red ones. What is the best way to do that?
[
{ code: "RED", value: 0},
{ code: "BLUE", value: 0},
{ code: "RED", value: 0},
{ code: "GREEN", value: 0},
{ code: "BLUE", value: 0},
{ code: "RED", value: 0},
{ code: "GREEN", value: 0},
{ code: "BLUE", value: 0}
]
Is it possible to do that with the sort function? What would the condition be in that case?
You could take an object for the wanted order.
var array = [{ code: "RED", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }],
order = { GREEN: 1, BLUE: 2, RED: 3 };
array.sort(function (a, b) {
return order[a.code] - order[b.code];
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For unknow colors/values, you could use a default value with
0, for sorting to top or
Infinity or as some suggest because of the ability for caculating Number.MAX_VALUE for sorting to the end,
or any other value for sorting inbetween the other groups.
At last you could sort the special treated items with an other sorting part, chained with logical OR ||.
var array = [{ code: "YELLOW", value: 0 }, { code: "BLACK", value: 0 }, { code: "RED", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }, { code: "RED", value: 0 }, { code: "GREEN", value: 0 }, { code: "BLUE", value: 0 }],
order = { GREEN: 1, BLUE: 2, RED: 3, default: Infinity };
array.sort(function (a, b) {
return (order[a.code] || order.default) - (order[b.code] || order.default) || a.code.localeCompare(b.code);
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Set the custom priority first
var codePriority = [ "GREEN", "BLUE", "RED" ];
Now use the same in sorting as
arr.sort( function(a,b){
if ( a.code == b.code ) return a.value - b.value;
return codePriority.indexOf( a.code ) - codePriority.indexOf( b.code ) ; notice this line
})
Demo
var arr = [
{ code: "RED", value: 0},
{ code: "BLUE", value: 0},
{ code: "RED", value: 0},
{ code: "GREEN", value: 0},
{ code: "BLUE", value: 0},
{ code: "RED", value: 0},
{ code: "GREEN", value: 0},
{ code: "BLUE", value: 0}
];
var codePriority = [ "GREEN", "BLUE", "RED" ];
arr.sort( function(a,b){
if ( a.code == b.code ) return a.value - b.value;
return codePriority.indexOf( a.code ) - codePriority.indexOf( b.code )
});
console.log( arr );
You could implement a schema array and sort according to element's index inside that schema array.
const a = ['GREEN', 'BLUE', 'RED'];
const o = [{code:"RED",value:0},{code:"BLUE",value:0},{code:"RED",value:0},{code:"GREEN",value:0},{code:"BLUE",value:0},{code:"RED",value:0},{code:"GREEN",value:0},{code:"BLUE",value:0}];
const r = o.slice().sort(({ code: q }, { code: w }) => a.indexOf(q) - a.indexOf(w));
console.log(r);
this is a function for sorting by a specific color.
const colors = [{
name: "T-shirt",
color: "red",
price: 20
},
{
name: "Shoes",
color: "yellow",
price: 20
},
{
name: "Pants",
color: "red",
price: 20
},
{
name: "Cap",
color: "yellow",
price: 20
},
{
name: "Skirt",
color: "red",
price: 15
},
]
let sortByColor = color => colors.sort((a, b) => a.color === color ? -1 : 1)
console.log(sortByColor('red'))
You can use the sort function i.e Array.prototype.sort() Visit https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
Firstly you have to decide whether you want to sort in ascending order or in descending order.
To sort in ascending order you can do something like this:
arr.sort((a, b) => {
return a.color < b.color ? -1 : a.color > b.color ? 1 : 0;
});
An to do it in descending order:
arr.sort((a, b) => {
return a.color > b.color ? -1 : a.color < b.color ? 1 : 0;
});
Now suppose you want a certain color sorted and displayed first. You can have a function like this:
const sortByKeyAsc = (arr,color) =>
arr.sort((a, b) => {
if(a.color < b.color || (a.color === color && b.color !== color)){
return -1;
}
if(a.color > b.color || (a.color !== color && b.color === color)){
return 1
}
return 0;
});
and you can use it like this:
const array1 = sortByKeyAsc(arr,'pink');
I was dealing with a case where I had to match a string status and sort by the various statuses specifically. .findIndex and .includes ended up being the best approach.
statusPriority sets the intended order. Once the indexes are found they can be compared and returned to the .sort
let records = [
{status: 'Record is ready to submit.', active: true, name: 'A'},
{status: 'Record has been sent.', active: true, name: 'B'},
{status: 'Activation is required.', active: true, name: 'C'},
{status: 'Record submission failed.', active: true, name: 'D'},
{status: 'Creation is pending.', active: true, name: 'E'},
]
console.log(records.map(r => r.status))
let statusPriority = ['creation', 'activation', 'sent', 'ready', 'failed'];
records.sort((a, b) => {
let aIndex = statusPriority.findIndex(status => a.status.toLowerCase().includes(status));
let bIndex = statusPriority.findIndex(status => b.status.toLowerCase().includes(status));
return aIndex - bIndex;
})
console.log(records.map(r => r.status))
You can sort color alphabetically by using this function
var sortedArr = arr.sort((first, second)=>{
return first.color < second.color ? -1 : 1
})

Categories