Filter things with changeable arguments - javascript

let products = [
{
"name": "Lenovo",
"price": "18000",
"model": "v580c"
},
{
"name": "Apple",
"price": "30000",
"model": "Iphone 6"
},
{
"name": "Nikon",
"price": "25000",
"model": "G290"
}]
I need to filter my products array with getProduct function, which accepts changeable list of arguments.
Argument can be either the name of the product and/or price within the minPrice, maxPrice, and/or model.
function getProduct(productName, minPrice, maxPrice, productModel) {
return products.filter(product => {
return product.price < maxPrice && product.price > minPrice && product.name == productName;
});
}
console.log(getProduct("Apple", 3540, 3000000000));
console.log(getProduct("Lenovo", 3540, 3000000000, "v580c"));

You can send an array of params as argument and write a logic to process them accordingly.
Sample:
function getProduct(array, params){
var list = array.filter(function(o){
return params.every(function(kv){
if(o.hasOwnProperty(kv.key)){
var cur = o[kv.key];
switch (kv.operation){
case ">": return cur > kv.value
case "<": return cur < kv.value
case "in": return cur.indexOf(kv.value) > -1
case "regex": return kv.value.test(cur)
default: return cur === kv.value
}
}
})
});
console.log(list);
return list;
}
var products=[{name:"Lenovo",price:"18000",model:"v580c"},{name:"Apple",price:"30000",model:"Iphone 6"},{name:"Nikon",price:"25000",model:"G290"}];
getProduct(products, [{key:"name", value: "Nikon"}])
getProduct(products, [
{key:"price", value: 20000, operation: ">"},
{key:"price", value: 40000, operation: "<"}
])
getProduct(products, [{key:"name", value: "e", operation: "in"}])
getProduct(products, [{key:"model", value: /\d{2,}/g, operation: "regex"}])

You can use an object with special structure for searching, if you need t search for more than one item. This proposal uses an object, with this structure for filtering:
{
name: 'Apple',
price: {
min: 3540, // both or a single border is possible
max: 60000
},
model: function (s) { return s.match(/s/); } // just search for a single letter
}
The algorithm looks for every property in search and if all comparisons are true, then the element is added to the result set.
function filter(array, search) {
return array.filter(function (a) {
return Object.keys(search).every(function (k) {
return (
a[k] === search[k] ||
typeof search[k] === 'object' && (
('min' in search[k]) && ('max' in search[k]) && search[k].min <= a[k] && a[k] <= search[k].max ||
('min' in search[k]) !== ('max' in search[k]) && (search[k].min <= a[k] || a[k] <= search[k].max)
) ||
typeof search[k] === 'function' && search[k](a[k])
);
});
});
}
var products = [{ name: "Lenovo", price: "18000", model: "v580c" }, { name: "Apple", price: "30000", model: "Iphone 6" }, { name: "Nikon", price: "25000", model: "G290" }, { name: "Foo", price: "10", model: "a1" }, { name: "Foo", price: "20", model: "a2" }, { name: "Foo", price: "30", model: "a3" }, { name: "Foo", price: "40", model: "a4" }, { name: "Foo", price: "50", model: "a5" }, { name: "Foo", price: "60", model: "a6" }, { name: "Foo", price: "70", model: "a7" }, { name: "Foo", price: "80", model: "a8" }, { name: "Foo", price: "90", model: "a9" }];
console.log(filter(products, { name: 'Foo', price: { min: 60 } }));
console.log(filter(products, { name: 'Foo', price: { max: 40 } }));
console.log(filter(products, { name: 'Foo', price: { min: 40, max: 60 } }));
console.log(filter(products, { name: 'Apple', price: { min: 3540, max: 60000 } }));
console.log(filter(products, { name: 'Lenovo', price: { min: 3540, max: 60000 }, model: 'v580c' }));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

How to sort/order multiple objects inside array?

This is my output:
const data = {
item : {
id: "1",
name: "aa",
group: [
{
id:"11",
order:0,
},
{
id:"33",
order:5,
},
{
id:"3",
order:1,
},
]
},
item2 : {
id: "2",
name: "aaa",
group: [
{
id:"111",
order:3,
},
{
id:"33",
order:1,
},
{
id:"3",
order:2,
},
]
}
}
I want to order my group object by order item. If it was an object, I could do it:
data.group.sort((a, b) => {
return a.order - b.order || a.order.localeCompare(b.order);
});
But it will override the elements and I will get only the lastest item. I believe that something else is missing to make it work the way I want.
This is the desired output:
const data = {
item : {
id: "1",
name: "aa",
group: [
{
id:"11",
order:0,
},
{
id:"3",
order:1,
},
{
id:"33",
order:5,
},
]
},
item2 : {
id: "2",
name: "aaa",
group: [
{
id:"33",
order:1,
},
{
id:"3",
order:2,
},
{
id:"111",
order:3,
},
]
}
}
How can i do that?
Try this code:
const data = {
item : {
id: "1",
name: "aa",
group: [
{
id:"11",
order:0,
},
{
id:"33",
order:5,
},
{
id:"3",
order:1,
},
]
},
item2 : {
id: "2",
name: "aaa",
group: [
{
id:"111",
order:3,
},
{
id:"33",
order:1,
},
{
id:"3",
order:2,
},
]
}
}
Object.keys(data).forEach(key => {
const item = data[key];
item.group = item.group.sort((a, b) => {
return a.order - b.order || a.order.localeCompare(b.order);
});
return item;
});
console.log(data);
Do this (CREDIT TO: flymaster)
Object.keys(dataINPT).forEach(key => {
const your = dataINPT[key];
your.group = your.group.sort((some, some2) => {
return some.order - some2.order || some.order.localeCompare(some2.order);
});
return your;
});
console.log(data);
Use the Object.values, forEach loop and apply sort.
Object.values(data).forEach(({ group }) =>
group.sort((a, b) => {
return a.order - b.order || a.order.localeCompare(b.order);
})
);
const data = {
item: {
id: "1",
name: "aa",
group: [
{
id: "11",
order: 0,
},
{
id: "33",
order: 5,
},
{
id: "3",
order: 1,
},
],
},
item2: {
id: "2",
name: "aaa",
group: [
{
id: "111",
order: 3,
},
{
id: "33",
order: 1,
},
{
id: "3",
order: 2,
},
],
},
};
Object.values(data).forEach(({ group }) =>
group.sort((a, b) => {
return a.order - b.order || a.order.localeCompare(b.order);
})
);
console.log(data);

Get all parent in a nested object using recursion

I have the following object
const object = {
id: "1",
name: "a",
children: [
{
id: "2",
name: "b",
children: [
{
id: "3",
name: "c"
}
]
},
{
id: "4",
name: "d"
}
]
};
I need a function that accept the object and the id of the last child and return the path, for example, the following call: getPath(object, '3'); should return [{id: 1}, {id: 2}, {id: 3}].
I created the function but I can access only to the first parent.
function getPath(model, id, parent) {
if (model == null) {
return;
}
if (model.id === id) {
console.log(model.id, parent.id)
}
if (model.children) {
model.children.forEach(child => getPath(child, id, model));
}
}
PS: The object has an unknown depth.
You could use a short circuit for iterating the children and hand over the path from the function with the target object.
function getPath(model, id) {
var path,
item = { id: model.id };
if (!model || typeof model !== 'object') return;
if (model.id === id) return [item];
(model.children || []).some(child => path = getPath(child, id));
return path && [item, ...path];
}
const object = { id: "1", name: "a", children: [{ id: "2", name: "b", children: [{ id: "3", name: "c" }] }, { id: "4", name: "d" }] };
console.log(getPath(object, '42')); // undefined
console.log(getPath(object, '3')); // [{ id: 1 }, { id: 2 }, { id: 3 }]
.as-console-wrapper { max-height: 100% !important; top: 0; }
This is pretty close. Consider passing the entire path array in your recursive function. The following is a slightly modified version of what you have that accomplishes this.
function getPath(model, id, path) {
if (!path) {
path = [];
}
if (model == null) {
return;
}
if (model.id === id) {
console.log(model.id, path)
}
if (model.children) {
model.children.forEach(child => getPath(child, id, [...path, model.id]));
}
}
const object = {
id: "1",
name: "a",
children: [
{
id: "2",
name: "b",
children: [
{
id: "3",
name: "c"
}
]
},
{
id: "4",
name: "d"
}
]
};
getPath(object, "3");
const object = {
id: "1",
name: "a",
children: [
{
id: "2",
name: "b",
children: [
{
id: "3",
name: "c"
},
{
id: "5",
name: "c"
}
]
},
{
id: "4",
name: "d"
}
]
};
const getPath = (obj, id, paths = []) => {
if (obj.id == id) return [{ id: obj.id }];
if (obj.children && obj.children.length) {
paths.push({ id: obj.id });
let found = false;
obj.children.forEach(child => {
const temPaths = getPath(child, id);
if (temPaths) {
paths = paths.concat(temPaths);
found = true;
}
});
!found && paths.pop();
return paths;
}
return null;
};
console.log(getPath(object, "5"));
console.log(getPath(object, "2"));
console.log(getPath(object, "3"));
console.log(getPath(object, "4"));
.as-console-row {color: blue!important}

how to filter array object using object property

I got an array of object
const devices = [{
deviceLocation: {
label: "Pure",
value: "pure"
},
deviceName: "test7"
devicePaymentMethods: [{
label: "ab",
value: "ab"
} {
label: "cd",
value: "cd"
} {
label: "ef",
value: "ef"
}]
deviceType: "iPad"
id: "001"
connected: false
enabled: false
},
{
deviceLocation: {
label: "kandy",
value: "kandy"
},
deviceName: "test4"
devicePaymentMethods: [{
label: "ab",
value: "ab"
} {
label: "cd",
value: "cd"
}]
deviceType: "iPad"
id: "004"
connected: false
enabled: false
}
]
I want to filter the array by object using deviceName,deviceLocation and devicePaymentMethods
Here is what I have already done and it is working for deviceName and deviceLocation but doesn't work for devicePaymentMethods
const filterByValue = (array, string) => {
return array.filter(o =>
Object.keys(o).some(k => {
if (k === "deviceName") {
return o[k].toLowerCase().includes(string.toLowerCase());
} else if (k === "deviceLocation") {
return o[k].label.toLowerCase().includes(string.toLowerCase());
} else if (k === "devicePaymentMethods") {
o[k].map(pay => {
if(pay.label.toLowerCase().includes(string.toLowerCase()))
return pay;
});
}
})
);
};
filterByValue(devices, "ab")
You forget to mentioned return while filtering the data inside map
return o[k].map(pay => {
if(pay.label.toLowerCase().includes(string.toLowerCase()))
return pay;
const devices = [{
deviceLocation: {
label: "Pure",
value: "pure"
},
deviceName: "test7",
devicePaymentMethods: [{
label: "ab",
value: "ab"
}, {
label: "cd",
value: "cd"
}, {
label: "ef",
value: "ef"
}],
deviceType: "iPad",
id: "001",
connected: false,
enabled: false,
},
{
deviceLocation: {
label: "kandy",
value: "kandy"
},
deviceName: "test4",
devicePaymentMethods: [{
label: "ab",
value: "ab"
}, {
label: "cd",
value: "cd"
}],
deviceType: "iPad",
id: "004",
connected: false,
enabled: false,
}
];
const filterByValue = (array, string) => {
return array.filter(o =>
Object.keys(o).some(k => {
if (k === "deviceName") {
return o[k].toLowerCase().includes(string.toLowerCase());
} else if (k === "deviceLocation") {
return o[k].label.toLowerCase().includes(string.toLowerCase());
} else if (k === "devicePaymentMethods") {
return o[k].some(pay => {
if (pay.label.toLowerCase().includes(string.toLowerCase())) {
return pay;
}
});
}
})
);
};
console.log(filterByValue(devices, "ab"));
console.log(filterByValue(devices, "ef"));
You could take a slightly different approach with an array of wanted keys and keys for nested array for search.
const
keys = [['deviceName'], ['deviceLocation', 'label'], ['devicePaymentMethods', 'label']],
filterByValue = (array, string) => array.filter(object => keys.some(([key, sub]) => {
if (!(key in object)) return false;
if (typeof object[key] === 'string' && object[key].toLowerCase() === string) return true;
if (Array.isArray(object[key]) && sub)
return object[key].some(o => o[sub].toLowerCase() === string);
})),
devices = [{ deviceLocation: { label: "Pure", value: "pure" }, deviceName: "test7", devicePaymentMethods: [{ label: "ab", value: "ab" }, { label: "cd", value: "cd" }, { label: "ef", value: "ef" }], deviceType: "iPad", id: "001", connected: false, enabled: false }, { deviceLocation: { label: "kandy", value: "kandy" }, deviceName: "test4", devicePaymentMethods: [{ label: "ab", value: "ab" }, { label: "cd", value: "cd" }], deviceType: "iPad", id: "004", connected: false, enabled: false }],
result = filterByValue(devices, "ab");
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sort by multiple objects in a array in Javascript

var customersObj= [
{ recordId: "123", groupID: "1992" ,memberID:"10" Name : "John" },
{ recordId: "141", groupID: "1994" ,memberID:"13", Name : "Arrow" },
{ recordId: "111", groupID: "1991",memberID:"12", Name : "Mike" }
];
I need to return the array by sort them first by recordId, then by groupID, then by memberID ...
I tried this but didn't get expected result"
return _.sortBy(customersObj,'recordID','groupID','memberID');
Can someone assist here on this...
Pay attention that your *ID are strings, so, I've used Array.map to convert them to ints, and then _.sortBy works expectedly.
I've added additional values to check the sub-sorting.
const customersObj = [{
recordId: "123",
groupID: "1992",
memberID: "10",
Name: "John"
}, {
recordId: "141",
groupID: "1994",
memberID: "13",
Name: "Arrow"
}, {
recordId: "111",
groupID: "1991",
memberID: "12",
Name: "Mike"
}, {
recordId: "123",
groupID: "1991",
memberID: "12",
Name: "Sean"
}, {
recordId: "123",
groupID: "1991",
memberID: "11",
Name: "Sara"
}];
const result = customersObj.map(item => ({
recordId: parseInt(item.recordId, 10),
groupID: parseInt(item.groupID, 10),
memberID: parseInt(item.memberID, 10),
Name: item.Name
}));
console.log(_.sortBy(result, 'recordId', 'groupID', 'memberID'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
Try use this approach:
const customersObj= [
{ recordId: "123", groupID: "1992" ,memberID:"10", Name : "John" },
{ recordId: "141", groupID: "1994" ,memberID:"13", Name : "Arrow" },
{ recordId: "111", groupID: "1991",memberID:"12", Name : "Mike" }
];
const sorted = customersObj.sort((a,b)=>{
return a.recordId - b.recordId || a.groupID - b.groupID || a.memberID - b.memberID;
})
console.log(`sorted`, sorted);
you can use sort method with lambda function to sort.
const list = [
{ color: 'white', size: 'XXL' },
{ color: 'red', size: 'XL' },
{ color: 'black', size: 'M' }
]
list.sort((a, b) => (a.color > b.color) ? 1 : -1) // you can add different conditions here.
to sort multiple fields, do it like this
customersObj.sort(function(a, b) {
return a["recordId"] - b["recordId"] || a["groupID"] - b["groupID"] || a["memberID"] - b["memberID"];
});
You can sort array of object using multiple values by the following method
var arrayOfObj = [
{ recordId: "123", groupID: "1992" ,memberID:"10" , Name : "John" },
{ recordId: "141", groupID: "1994" ,memberID:"13", Name : "Arrow" },
{ recordId: "111", groupID: "1991",memberID:"12", Name : "Mike" }
];
let sortBy = [{
prop:'recordId',
direction: 1
},{
prop:'lastName',
direction: 1
},{
prop:'memberID',
direction: 1
}];
arrayOfObj.sort(function(a,b){
let i = 0, result = 0;
while(i < sortBy.length && result === 0) {
result = sortBy[i].direction*(a[ sortBy[i].prop ].toString() < b[ sortBy[i].prop ].toString() ? -1 : (a[ sortBy[i].prop ].toString() > b[ sortBy[i].prop ].toString() ? 1 : 0));
i++;
}
return result;
})
console.log(arrayOfObj, ":::::");
With lodash, could take an array of keys and take the right spelling of the wanted keys.
var customersObj = [{ recordId: "123", groupID: "1992", memberID: "10", Name: "John" }, { recordId: "141", groupID: "1994", memberID: "13", Name: "Arrow" }, { recordId: "111", groupID: "1991",
memberID: "12", Name: "Mike" }];
console.log(_.sortBy(customersObj, ['recordId', 'groupID', 'memberID']));
// ^ ^ ^
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Hi i tried solve your problem :)
const display = document.querySelector(".display");
var customersObj= [
{ recordId: "123", groupID: "1992" ,memberID:"10", Name : "John" },
{ recordId: "141", groupID: "1994" ,memberID:"13", Name : "Arrow" },
{ recordId: "111", groupID: "1991",memberID:"12", Name : "Mike" }
];
customersObj.sort(function (a, b) {
return a.recordId - b.recordId || b.groupID - a.groupID || c.memberID - c.memberID;
});
customersObj.map(obj => {
const item = document.createElement("div");
item.textContent += obj.recordId + " " + obj.groupID + " " + obj.memberID +" "+ obj.Name;
display.appendChild(item);
});
<div class="display">
</div>

merge array object with three keys

There are two arrays of objects, a and b. Key is 'id' ,'isfix' ,'groupid'.
For example
a.id === b.id && a.isfix === b.isfix && a.groupid===b.groupdid
The sequence array is not the same.
I expected c.
I hope you don't use lodash. I like es6 or vanila js. thanks..
I think reduce and map and filter.. but Not as well as I thought.
I think make function...
input is a,b and output is c
var a = [
{
id:"555",
groupID:"10",
isFix:false,
tolerancePlus:5,
toleranceMinus:3
},
{
id:"123",
groupID:"10",
isFix:true,
tolerancePlus:"",
toleranceMinus:7
},
{
id:"555",
groupID:"10",
isFix:true,
tolerancePlus:11,
toleranceMinus:6
}
]
var b = [
{
id:"123",
groupID:"10",
isFix:true,
tolerance:{
min: null,
plus : null
}
},
{
id:"555",
groupID:"10",
isFix:false,
tolerance:{
min: null,
plus : null
}
},
{
id:"555",
groupID:"10",
isFix:true,
tolerance:{
min: null,
plus : null
}
},
]
var c = [
{
id:"123",
groupID:"10",
isFix:true,
tolerance:{
min: 7,
plus : 0 // if "" that value is 0
}
},
{
id:"555",
groupID:"10",
isFix:false,
tolerance:{
min: 3,
plus : 5
}
},
{
id:"555",
groupID:"10",
isFix:true,
tolerance:{
min: 6,
plus : 11
}
},
]
here's a way to do it :
it uses :
Array.reduce
Array.push
the ~ (bitwise not) operator
disclaimer : since it uses the ~ operator, it can (and will) break if your tolerance are not 32-bit integers (it's undefined behavior AFAIR)
// create your arrays
var a = [{id:"555",groupID:"10",isFix:false,tolerancePlus:5,toleranceMinus:3},{id:"123",groupID:"10",isFix:true,tolerancePlus:"",toleranceMinus:7},{id:"555",groupID:"10",isFix:true,tolerancePlus:11,toleranceMinus:6}]
var b = [{id:"123",groupID:"10",isFix:true,tolerance:{min: null,plus : null}},{id:"555",groupID:"10",isFix:false,tolerance:{min: null,plus : null}},{id:"555",groupID:"10",isFix:true,tolerance:{min: null,plus : null}},]
// loop over b, creating a new array
let c = b.reduce((acc, value) => {
// find an object from a which correspond to the current object
let linked = a.find(val => val.id === value.id && value.groupID === val.groupID && val.isFix === value.isFix)
// if it exists push it in the new array
if(linked) {
acc.push({
id: linked.id,
groupID: linked.groupID,
isFix: linked.isFix,
tolerance:{
min: ~~linked.toleranceMinus, // the ~~value here use some magic to transform
plus : ~~linked.tolerancePlus // everything that's not a number to 0
}
})
}
return acc
}, [])
console.log(c)
var wantedC = [{id:"123",groupID:"10",isFix:true,tolerance:{min: 7,plus : 0}},{id:"555",groupID:"10",isFix:false,tolerance:{min: 3,plus : 5}},{id:"555",groupID:"10",isFix:true,tolerance:{min: 6,plus : 11}}]
console.log(JSON.stringify(wantedC) === JSON.stringify(c))
Here is the Logic in vanilla JS:
var a = [
{
id: '555',
groupID: '10',
isFix: false,
tolerancePlus: 5,
toleranceMinus: 3
},
{
id: '123',
groupID: '10',
isFix: true,
tolerancePlus: '',
toleranceMinus: 7
},
{
id: '555',
groupID: '10',
isFix: true,
tolerancePlus: 11,
toleranceMinus: 6
}
]
var b = [
{
id: '123',
groupID: '10',
isFix: true,
tolerance: {
min: null,
plus: null
}
},
{
id: '555',
groupID: '10',
isFix: false,
tolerance: {
min: null,
plus: null
}
},
{
id: '555',
groupID: '10',
isFix: true,
tolerance: {
min: null,
plus: null
}
}
]
var c = a.map(data1 => {
const toleranceData = b.map(data2 => {
if (
data1.id === data2.id &&
data1.isfix === data2.isfix &&
data1.groupdid === data2.groupdid
) {
return {
tolerance: {
min: data1.toleranceMinus || 0,
plus: data1.tolerancePlus || 0
}
}
}
})
const { tolerance } = toleranceData.filter(d => d)[0]
const { id, groupID, isFix } = data1
return { id, groupID, isFix, tolerance }
})
console.log(c)
So we have 2 arrays of objects:
And we have a statement a.id === b.id && a.isFix === b.isFix && a.groupid===b.groupdid
To get what you need you can use arr.find() inside a arr.map() method and make our changes:
const a = [{ id: "555", groupID: "10", isFix: false, tolerancePlus: 5, toleranceMinus: 3 }, { id: "123", groupID: "10", isFix: true, tolerancePlus: "", toleranceMinus: 7 }, { id: "555", groupID: "10", isFix: true, tolerancePlus: 11, toleranceMinus: 6 } ]
const b = [{ id: "123", groupID: "10", isFix: true, tolerance: { min: null, plus: null } }, { id: "555", groupID: "10", isFix: false, tolerance: { min: null, plus: null } }, { id: "555", groupID: "10", isFix: true, tolerance: { min: null, plus: null } }, ]
let c = b.map(obj => {
const valuesObj = a.find(item => item.id === obj.id && item.isFix === obj.isFix && item.groupid === obj.groupdid);
if (valuesObj) {
obj.tolerance.min = valuesObj.toleranceMinus || 0;
obj.tolerance.plus = valuesObj.tolerancePlus || 0;
}
return obj;
})
console.log(c);

Categories

Resources