Need for some help here. Looking for a hint to solve this issue :
The goal is to filter arrayOfObject and get all objects with the property fruits containing all the element from the given array.
const arrayOfObject = [
{
id: 1,
country: 'USA',
fruits: ["APPLE", "ORANGE", "BANANA"]
},
{
id: 2,
country: 'Canada',
fruits: ["APPLE"]
},
{
id: 3,
country: 'France',
fruits: ["ORANGE", "BANANA", "LEMON"]
},
{
id: 4,
country: 'Mexico',
fruits: ["BANANA", "PYTHON", "CHERRY"]
},
{
id: 5,
country: 'Ukraine',
fruits: ["APPLE", "ORANGE", "CHERRY"]
},
{
id: 6,
country: 'Italy',
fruits: ["APPLE", "ORANGE", "BANANA", "LEMON", "CHERRY"]
}
];
First exemple with this given array :
const firstArrayOfFruits = ["APPLE","ORANGE","BANANA"];
Should render =>
[
{
id: 1,
country: 'USA',
fruits: ["APPLE", "ORANGE", "BANANA"]
},
{
id: 6,
country: 'Italy',
fruits: ["APPLE", "ORANGE", "BANANA", "LEMON", "CHERRY"]
}
]
Second exemple with this given array :
const secondArrayOfFruits = ["APPLE","ORANGE"];
Should render =>
[
{
id: 1,
country: 'USA',
fruits: ["APPLE", "ORANGE", "BANANA"]
},
{
id: 5,
country: 'Ukraine',
fruits: ["APPLE", "ORANGE", "CHERRY"]
},
{
id: 6,
country: 'Italy',
fruits: ["APPLE", "ORANGE", "BANANA", "LEMON", "CHERRY"]
}
]
You can use Array.prototype.filter:
const arrayOfObject = [{
id: 1,
country: 'USA',
fruits: ["APPLE", "ORANGE", "BANANA"]
},
{
id: 2,
country: 'Canada',
fruits: ["APPLE"]
},
{
id: 3,
country: 'France',
fruits: ["ORANGE", "BANANA", "LEMON"]
},
{
id: 4,
country: 'Mexico',
fruits: ["BANANA", "PYTHON", "CHERRY"]
},
{
id: 5,
country: 'Ukraine',
fruits: ["APPLE", "ORANGE", "CHERRY"]
},
{
id: 6,
country: 'Italy',
fruits: ["APPLE", "ORANGE", "BANANA", "LEMON", "CHERRY"]
}
];
const firstArrayOfFruits = ["APPLE", "ORANGE", "BANANA"];
var arr = arrayOfObject.filter(item => item.fruits.filter(fruit => firstArrayOfFruits.indexOf(fruit) + 1).length >= firstArrayOfFruits.length);
console.log(arr);
Using ES6 some() function is useful because when finds an entry it will return true and doesnt check the rest, so you can save some calcs, time and CPU
const filtered = arrayOfObject.filter(obj => {
if(obj.fruits.some(fruit => fruitsLisToCheck.includes(fruit)))
return obj
})
const fruitsLisToCheck = ['BANANA', 'APPLE'];
const arrayOfObject = [
{
id: 2,
country: 'Canada',
fruits: ["APPLE"]
},
{
id: 3,
country: 'France',
fruits: ["BANANA"]
},
{
id: 4,
country: 'Mexico',
fruits: ["CHERRY"]
},
];
Related
I have two array and need to take specific key value pair and assign to third one array and it will also take care of duplication entry.
First Array :
[
{id: 2, name: "HSBC", status: "YES"},
{id: 3, name: "Morgan Stanley", status: "Pending"}
]
Second Array:
[
{id: 1, name: "Deutsche Bank", category: "EQUITIES"},
{id: 2, name: "HSBC", category: "EQUITIES"},
{id: 3, name: "Morgan Stanley", category: "EQUITIES"},
{id: 4, name: "Credit Suisse", category: "EQUITIES"},
]
From above two arrays I need to take name and status field and create the new array. Like below:
[
{ brokerName: "HSBC", statis: "YES"},
{ brokerName: "Morgan Stanley", statis: "Pending"},
{ brokerName: "Deutsche Bank", statis: ""},
{ brokerName: "Credit Suisse", statis: ""},
]
TIA.
Stackblitz
let arr1 = [{id: 1, name: "name", status: "YES"}];
let arr2 = [{id: 1, name: "name", category: "EQUITIES"}];
let sumbit = [];
for (let i=0; i<arr1.length; i++) {
let is_there = false;
for (let j=0; j<arr2.length; j++) {
if (arr1[i].name == arr[j].name) {
submit.push({brokerName: arr1[i].name, statis: arr1[i].status});
is_there = true;
}
}
if (!is_there) submit.push({brokerName: arr1[i].name, statis: ""})
}
You could just write the code :D
Here is an example:
const array1 = [
{id: 2, name: "HSBC", status: "YES"},
{id: 3, name: "Morgan Stanley", status: "Pending"}
];
const array2 = [
{id: 1, name: "Deutsche Bank", category: "EQUITIES"},
{id: 2, name: "HSBC", category: "EQUITIES"},
{id: 3, name: "Morgan Stanley", category: "EQUITIES"},
{id: 4, name: "Credit Suisse", category: "EQUITIES"},
];
// returns { name, status } recoreds from any number of arrays
function getBrokersDataFromArrays(...arrays) {
const allBrokers = new Map();
// collect all the available data for all the brokers
arrays.flat().forEach(broker => {
if (allBrokers.has(broker.name)) {
allBrokers.set(broker.name, { ...allBrokers.get(broker.name), ...broker });
} else {
allBrokers.set(broker.name, broker);
}
});
// return only { name, status } fields from the collected brokers
return Array.from(allBrokers.values()).map(broker => (
{ name: broker.name, status: broker.status }
));
}
const brokersData = getBrokersDataFromArrays(array1, array2);
console.log(brokersData);
let array1 = [
{id: 2, name: "HSBC", status: "YES"},
{id: 3, name: "Morgan Stanley", status: "Pending"}
]
let array2 = [
{id: 1, name: "Deutsche Bank", category: "EQUITIES"},
{id: 2, name: "HSBC", category: "EQUITIES"},
{id: 3, name: "Morgan Stanley", category: "EQUITIES"},
{id: 4, name: "Credit Suisse", category: "EQUITIES"},
]
// filter data which are present into both array
const result1 = array1.filter(o => array2.some(({ name }) => o.name === name));
// filter data which are present into array1 but not into array2
const result2 = array1.filter((o1) => {
return !array2.some((o2) => {
return o1.name === o2.name;
});
})
// filter data which are present into array2 but not into array1
const result3 = array2.filter((o1) => {
return !array1.some((o2) => {
return o1.name === o2.name;
});
})
// concat all result
let result = (result1.concat(result2)).concat(result3)
let finalArr = []
for (let obj of result) {
finalArr.push({ brokerName: obj.name, status: obj.status ? obj.status : "" })
}
Hi i'm trying to organize this data, i can arrange this product list by index of userSettings.categories array, i need also to sort the products by id like the sortedProducts property, this is what i've been trying for now, thanks in advance community.
let products = [
{id: 1, name: 'Brasilian', category: 'cofee'},
{id: 2, name: 'Colombian', category: 'cofee'},
{id: 3, name: 'Apple', category: 'fruit'},
{id: 4, name: 'Strawberry', category: 'fruit'},
{id: 5, name: 'Banana', category: 'fruit'},
{id: 6, name: 'Pepper', category: 'spices'},
{id: 7, name: 'Salt', category: 'spices'}
]
let userSettings = {
categories: [
{name: 'fruit', sortedProducts: [4, 3, 5]},
{name: 'spices', sortedProducts: [6, 7]},
{name: 'cofee', sortedProducts: [2, 1]},
]
}
let arrangedProducts = userSettings.categories.map(c => products.filter(o => o.category == c.name));
console.log(arrangedProducts);
expectedOutput = [
[
{id: 4, name: 'Strawberry', category: 'fruit'},
{id: 3, name: 'Apple', category: 'fruit'},
{id: 5, name: 'Banana', category: 'fruit'}
],
[
{id: 6, name: 'Pepper', category: 'spices'},
{id: 7, name: 'Salt', category: 'spices'}
],
[
{id: 2, name: 'Colombian', category: 'cofee'},
{id: 1, name: 'Brasilian', category: 'cofee'}
]
];
console.log(expectedOutput);
You can try
let arrangedProducts = userSettings.categories.map(
c => c.sortedProducts.map(
id => products.find(product => product.id === id)
)
);
Or if you have a lot of items in the future and want it to run faster, you can use hash table
const hashProduct = products.reduce((a, b) => ({...a, [b.id]: b}), {});
console.log(
userSettings.categories.map(
c => c.sortedProducts.map(id => hashProduct[id])
)
);
Try:
let products=[{id:1,name:"Brasilian",category:"cofee"},{id:2,name:"Colombian",category:"cofee"},{id:3,name:"Apple",category:"fruit"},{id:4,name:"Strawberry",category:"fruit"},{id:5,name:"Banana",category:"fruit"},{id:6,name:"Pepper",category:"spices"},{id:7,name:"Salt",category:"spices"}]
let userSettings={categories:[{name:"fruit",sortedProducts:[4,3,5]},{name:"spices",sortedProducts:[6,7]},{name:"cofee",sortedProducts:[2,1]}]};
let result = []
userSettings.categories.forEach((e) => { let arr = []; e.sortedProducts.forEach(f => arr.push(products.filter(g => g.id == f))); result.push(arr) })
console.log(result);
You can sort by the indexOf in the sortedProducts array
userSettings.categories
.map(c => products
.filter(o => o.category == c.name)
.sort((a, b) =>
c.sortedProducts.indexOf(a.id) - c.sortedProducts.indexOf(b.id)))
let products = [{
id: 1,
name: 'Brasilian',
category: 'cofee'
},
{
id: 2,
name: 'Colombian',
category: 'cofee'
},
{
id: 3,
name: 'Apple',
category: 'fruit'
},
{
id: 4,
name: 'Strawberry',
category: 'fruit'
},
{
id: 5,
name: 'Banana',
category: 'fruit'
},
{
id: 6,
name: 'Pepper',
category: 'spices'
},
{
id: 7,
name: 'Salt',
category: 'spices'
}
]
let userSettings = {
categories: [{
name: 'fruit',
sortedProducts: [4, 3, 5]
},
{
name: 'spices',
sortedProducts: [6, 7]
},
{
name: 'cofee',
sortedProducts: [2, 1]
},
]
}
let expectedOutput = userSettings.categories.map(c => products.filter(o => o.category == c.name).sort((a, b) => c.sortedProducts.indexOf(a.id) - c.sortedProducts.indexOf(b.id)));
console.log(expectedOutput);
I need some help to sort this data out, i have an array of products and i need to sort and display by settings configuration. The output must have the same order as settings array (index) and if display is true. Thanks in advance. This is what i tryed:
var products = [
{id: 0, name: 'Chocolate', category: 'Sweet'},
{id: 1, name: 'Almendras', category: 'Fruit'},
{id: 2, name: 'Nueces', category: 'Fruit'},
{id: 3, name: 'Mermelada', category: 'Jam'},
{id: 4, name: 'Alfajor', category: 'Sweet'},
{id: 5, name: 'Queso', category: 'UwU'},
{id: 6, name: 'Arandanos', category: 'Fruit'},
{id: 7, name: 'Maracuya', category: 'Fruit'}
];
let settings = [
{
name: 'Fruit',
display: true
},
{
name: 'Jam',
display: false
},
{
name: 'Sweet',
display: true
},
{
name: 'UwU',
display: true
}
]
let group = products.reduce((r, a) => {
r[a.category] = [...r[a.category] || [], a];
return r;
}, {});
let arrangedProducts = Object.keys(group);
console.log(group);
console.log(arrangedProducts);
This is my expected output:
/*
expected result = [
[
{id: 1, name: 'Almendras', category: 'Fruit'},
{id: 2, name: 'Nueces', category: 'Fruit'},
{id: 6, name: 'Arandanos', category: 'Fruit'},
{id: 7, name: 'Maracuya', category: 'Fruit'}
],
[
{id: 0, name: 'Chocolate', category: 'Sweet'},
{id: 4, name: 'Alfajor', category: 'Sweet'}
],
[
{id: 5, name: 'Queso', category: 'UwU'}
]
]
*/
Solution
Making of groups
Apply settings and retrieve the result
const products = [
{ id: 0, name: "Chocolate", category: "Sweet" },
{ id: 1, name: "Almendras", category: "Fruit" },
{ id: 2, name: "Nueces", category: "Fruit" },
{ id: 3, name: "Mermelada", category: "Jam" },
{ id: 4, name: "Alfajor", category: "Sweet" },
{ id: 5, name: "Queso", category: "UwU" },
{ id: 6, name: "Arandanos", category: "Fruit" },
{ id: 7, name: "Maracuya", category: "Fruit" },
];
const productsGroup = products.reduce((r, a) => {
r[a.category] = [...(r[a.category] || []), a];
return r;
}, {});
function applySettings(settings) {
return settings.filter((s) => s.display).map((s) => productsGroup[s.name]);
}
console.log(
applySettings([
{
name: "Fruit",
display: true,
},
{
name: "Jam",
display: false,
},
])
);
console.log(
applySettings([
{
name: "Fruit",
display: true,
},
{
name: "Sweet",
display: true,
},
{
name: "UwU",
display: true,
},
])
);
You can filter your settings list based on the display property and then use Array.map to return a list of objects in products that match the category:
const products = [
{id: 0, name: 'Chocolate', category: 'Sweet'},
{id: 1, name: 'Almendras', category: 'Fruit'},
{id: 2, name: 'Nueces', category: 'Fruit'},
{id: 3, name: 'Mermelada', category: 'Jam'},
{id: 4, name: 'Alfajor', category: 'Sweet'},
{id: 5, name: 'Queso', category: 'UwU'},
{id: 6, name: 'Arandanos', category: 'Fruit'},
{id: 7, name: 'Maracuya', category: 'Fruit'}
];
const settings = [
{ name: 'Fruit', display: true },
{ name: 'Jam', display: false },
{ name: 'Sweet', display: true },
{ name: 'UwU', display: true }
];
const result = settings
.filter(c => c.display)
.map(c => products.filter(o => o.category == c.name));
console.log(result);
Note that this code does filter the products array for each settings value that has display:true, so may be slow for large arrays. However filter is pretty low overhead and testing with OP's sample data shows this to run 3x the speed of the reduce version; and with a larger products array (99 entries) to run 10x faster.
This should be pretty quick, because it continues on to the next iteration without executing the inner loop when display is false:
var products = [
{id: 0, name: 'Chocolate', category: 'Sweet'},
{id: 1, name: 'Almendras', category: 'Fruit'},
{id: 2, name: 'Nueces', category: 'Fruit'},
{id: 3, name: 'Mermelada', category: 'Jam'},
{id: 4, name: 'Alfajor', category: 'Sweet'},
{id: 5, name: 'Queso', category: 'UwU'},
{id: 6, name: 'Arandanos', category: 'Fruit'},
{id: 7, name: 'Maracuya', category: 'Fruit'}
];
let settings = [
{
name: 'Fruit',
display: true
},
{
name: 'Jam',
display: false
},
{
name: 'Sweet',
display: true
},
{
name: 'UwU',
display: true
}
];
function sortProducts(){
const r = [];
let i = -1;
for(let s of settings){
if(!s.display){
continue;
}
i++;
for(let o of products){
if(s.name === o.category){
if(r[i]){
r[i].push(o);
}
else{
r.push([o]);
}
}
}
}
return r;
}
console.log(sortProducts());
I believe I have an array of javascript objects as follows, and I am trying to filter out all but the lowest prices for each item:
Have:
const fruits = [
{id: 1, fruit: "apple", store: "store1", price: 1},
{id: 2, fruit: "apple", store: "store2", price: 1.25},
{id: 3, fruit: "banana", store: "store1", price: 0.5},
{id: 4, fruit: "banana", store: "store2", price: 0.75},
{id: 5, fruit: "banana", store: "store3", price: 0.75}
];
Want:
[
{id: 1, fruit: "apple", store: "store1", price: 1},
{id: 3, fruit: "banana", store: "store1", price: 0.5}
];
I imagine in SQL this would be accomplished with a group by statement such as "select fruit, min(price) from table group by fruit", but am not sure how I might accomplish this in its current object form.
I am looking for a JavaScript solution but am open to changing the data structure or using a framework if needed. I am already using React.js if that is relevant. Any guidance?
object assign and reduce:
const fruits =
[ { id: 1, fruit: "apple", store: "store1", price: 1 }
, { id: 2, fruit: "apple", store: "store2", price: 1.25 }
, { id: 3, fruit: "banana", store: "store1", price: 0.5 }
, { id: 4, fruit: "banana", store: "store2", price: 0.75 }
, { id: 5, fruit: "banana", store: "store3", price: 0.75 }
]
const mini = fruits.reduce((a,c)=>
{
let x = a.find(e=>e.fruit===c.fruit)
if (!x) a.push(Object.assign({},c))
else if (x.price > c.price) Object.assign(x,c)
return a
},[])
console.log( mini )
– Dave Newton : . With a map/object-based solution you iterate fruits once and let the result object handle lookups.
there is an other way for this :
const fruits =
[ { id: 1, fruit: "apple", store: "store1", price: 1 }
, { id: 2, fruit: "apple", store: "store2", price: 1.25 }
, { id: 3, fruit: "banana", store: "store1", price: 0.5 }
, { id: 4, fruit: "banana", store: "store2", price: 0.75 }
, { id: 5, fruit: "banana", store: "store3", price: 0.75 }
]
const mini = fruits.reduce((a,c,i,t)=>
{
if (!a.find(e=>e.fruit===c.fruit))
a.push(t.filter(e=>e.fruit===c.fruit).reduce((r,n)=>r.price<n.price?r:n) )
return a
},[])
console.log( mini )
You can do this via a reduce operation, creating a map of category (fruit) to lowest price records.
For example
const fruits = [
{id: 1, fruit: "apple", store: "store1", price: 1},
{id: 2, fruit: "apple", store: "store2", price: 1.25},
{id: 3, fruit: "banana", store: "store1", price: 0.5},
{id: 4, fruit: "banana", store: "store2", price: 0.75},
{id: 5, fruit: "banana", store: "store3", price: 0.75}
]
const result = [...fruits.reduce((map, entry) => {
// check for an existing record and if it has a greater price
if (!map.has(entry.fruit) || map.get(entry.fruit).price > entry.price) {
// set the new record for this category
map.set(entry.fruit, entry)
}
return map
}, new Map()).values()] // now just get the values
console.info(result)
If there are multiple entries with the same price, this will keep the first one found. If you want to keep the last, use a >= comparison instead.
groupBy is a good commonly needed operation to have handy. I'd use that first to group the objects by fruit. The second reduce (minInArray) also is a commonly used form to find min or max in an array. Together they produce the min for each fruit type...
const groupBy = (array, key) => {
return array.reduce(function(r, a) {
r[a[key]] = r[a[key]] || []
r[a[key]].push(a)
return r
}, {})
}
const minInArray = (array, key) => {
return array.reduce((prev, curr) => {
return prev[key] < curr[key] ? prev : curr
})
}
const fruits = [{
id: 1,
fruit: "apple",
store: "store1",
price: 1
}, {
id: 2,
fruit: "apple",
store: "store2",
price: 1.25
}, {
id: 3,
fruit: "banana",
store: "store1",
price: 0.5
}, {
id: 4,
fruit: "banana",
store: "store2",
price: 0.75
}, {
id: 5,
fruit: "banana",
store: "store3",
price: 0.75
}];
let groups = groupBy(fruits, 'fruit')
let minPrices = Object.keys(groups).map(fruit => {
return minInArray(groups[fruit], 'price')
})
console.log(minPrices)
I am struggling to group by an array with it's sub-array. Here is my original array:
var people = [
{
name: "Bob",
age: "20",
car: {
colour: "Blue",
size: "Big",
rpm: "380"
}
},
{
name: "Mary",
age: "21",
car: {
colour: "Orange",
size: "Small",
rpm: "20"
}
},
{
name: "Janet",
age: "22",
car: {
colour: "Blue",
size: "Big",
rpm: "380"
}
}
];
And I would like to group by the colour of the car object into this form:
var cars = [
{
colour: "Blue",
size: "Big",
rpm: "380",
people: [{ name: "Bob", age: "20" }, { name: "Janet", age: "22" }]
},
{
colour: "Orange",
size: "Small",
rpm: "20",
people: [{ name: "Mary", age: "21" }]
}
];
I am relatively new to JavaScript so any help you can provide will be appreciated. Any external libraries are welcome.
EDIT
To answer #ths, I was able to successfully extract out the car object to the main array using this code:
resultArray = [];
people.forEach(function(people) {
let carObj = people.car;
console.log("TCL: carObj", carObj)
carObj["people"] = people;
resultArray.push(carObj);
});
But I had trouble combining the arrays into the different car types.
var people = [
{
name: "Bob",
age: "20",
car: {
colour: "Blue",
size: "Big",
rpm: "380"
}
},
{
name: "Mary",
age: "21",
car: {
colour: "Orange",
size: "Small",
rpm: "20"
}
},
{
name: "Janet",
age: "22",
car: {
colour: "Blue",
size: "Big",
rpm: "380"
}
}
];
let carMap = {};
people.forEach(p => {
const carKey = `${p.car.colour}-${p.car.size}-${p.car.rpm}`;
if (carKey in carMap) {
carMap[carKey].people.push({
name: p.name,
age: p.age
});
} else {
carMap[carKey] = {
...p.car,
people: [{
name: p.name,
age: p.age
}]
};
}
})
console.log(Object.values(carMap));
Create a car-people Map. Define a carkey that combined by the attribute of car. Finally, get values of the carMap.
The .reduce method can be used to transform arrays into objects with/arrays with a different structure:
var people = [
{
name: "Bob",
age: "20",
car: {
colour: "Blue",
size: "Big",
rpm: "380"
}
},
{
name: "Mary",
age: "21",
car: {
colour: "Orange",
size: "Small",
rpm: "20"
}
},
{
name: "Janet",
age: "22",
car: {
colour: "Blue",
size: "Big",
rpm: "380"
}
}
];
const generateId = (object) => Object.keys(object).map(key => key + object[key]).join('-');
var personByCar = Object.values(people.reduce((acc, person) => {
// Uniquely identify the car properties:
const carId = generateId(person.car);
// Add the people property to store related persons
if(!acc.hasOwnProperty(carId)){
acc[carId] = {...person.car, people: []};
}
// Add the person
acc[carId].people.push({person});
return acc;
}, {}));
console.log(personByCar)
More info about reduce: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce