Multiple filter conditions in Lodash - javascript

I have an Array of Objects containing product information where there are categories and colors as fields. Now, I have another array containing which categories and which colors to show.
Main Array:
products: [{
id: 1,
name: 'Product 1',
category: 'Home',
skill: 'Easy',
color: 'blue',
price: 100.00
}, {
id: 2,
name: 'Product 2',
category: 'Home',
skill: 'Intermediate',
color: 'red',
price: 120.00
}, {
id: 3,
name: 'Product 3',
category: 'Office',
skill: 'Intermediate',
color: 'green',
price: 190.00
}, {
id: 4,
name: 'Product 4',
category: 'Office',
skill: 'Advanced',
color: 'blue',
price: 260.00
}, {
id: 5,
name: 'Product 5',
category: 'Warehouse',
skill: 'Advanced',
color: 'white',
price: 321.00
}, {
id: 6,
name: 'Product 6',
category: 'Farm',
skill: 'Intermediate',
color: 'red',
price: 120.00
}, {
id: 7,
name: 'Product 7',
category: 'Space',
skill: 'Advanced',
color: 'green',
price: 150.00
}, {
id: 8,
name: 'Product 8',
category: 'Bathroom',
skill: 'Easy',
color: 'black',
price: 9.00
}],
My another array containing filter options:
selectedFilters: {
categories : ["home", "bathroom"] ,
colors : ["blue", "red"]
}
Now I want my output as:
[{
id: 1,
name: 'Product 1',
category: 'Home',
skill: 'Easy',
color: 'blue',
price: 100.00
}, {
id: 2,
name: 'Product 2',
category: 'Home',
skill: 'Intermediate',
color: 'red',
price: 120.00
}]
I tried the normal array filter method:
this.filteredProducts = this.products.filter(prod => {
// [prod.category, prod.color].some(val => this.selectedFilters.includes(val))
console.log(this.selectedFilters);
for (let i = 0; i < this.selectedFilters.length; i++) {
// console.log('Selected Category : ', this.selectedFilters[i]);
// console.log('Product Category : ', prod.category);
if (prod.category == this.selectedFilters[i]) {
console.log('Called category');
return true;
} else if (prod.color == this.selectedFilters[i]) {
console.log('Called color');
return true;
} else {
console.log('Called else');
continue;
}
}
});
How can I achieve this using array filter functions or Lodash functions?

No need for a library, use the standard .filter method to filter an array, check to see if each object's color and category is included in the selectedFilters object:
const products = [{
id: 1,
name: 'Product 1',
category: 'Home',
skill: 'Easy',
color: 'blue',
price: 100.00
}, {
id: 2,
name: 'Product 2',
category: 'Home',
skill: 'Intermediate',
color: 'red',
price: 120.00
}, {
id: 3,
name: 'Product 3',
category: 'Office',
skill: 'Intermediate',
color: 'green',
price: 190.00
}, {
id: 4,
name: 'Product 4',
category: 'Office',
skill: 'Advanced',
color: 'blue',
price: 260.00
}, {
id: 5,
name: 'Product 5',
category: 'Warehouse',
skill: 'Advanced',
color: 'white',
price: 321.00
}, {
id: 6,
name: 'Product 6',
category: 'Farm',
skill: 'Intermediate',
color: 'red',
price: 120.00
}, {
id: 7,
name: 'Product 7',
category: 'Space',
skill: 'Advanced',
color: 'green',
price: 150.00
}, {
id: 8,
name: 'Product 8',
category: 'Bathroom',
skill: 'Easy',
color: 'black',
price: 9.00
}];
const selectedFilters = {
categories : ["home", "bathroom"] ,
colors : ["blue", "red"]
};
const { categories, colors } = selectedFilters;
const filteredProducts = products.filter(({ category, color }) => (
categories.includes(category.toLowerCase()) && colors.includes(color.toLowerCase())
));
console.log(filteredProducts);

Related

JS push object with dynamic keys and values to an array

I have an array of objects with dynamic keys and values (so not all objects have category_id, size and so on) but I simplified it to this:
let products_row = [
{
id: 1,
category_id: 11,
options: {
'modelName1': {
size: '2 feet',
colour: 'red',
is_new: true
},
'modelName2': {
size: '4 feet',
colour: 'black',
is_new: true
},
}
},
{
id: 2,
category_id: 21,
options: {
'modelName11': {
size: '2 feet',
colour: 'white',
is_new: false
},
'modelName12': {
size: '4 feet',
colour: 'white',
is_new: false
},
}
},
{
id: 3,
category_id: 31,
options: {
'modelName21': {
size: '8 feet',
colour: 'white',
is_new: false
},
'modelName22': {
size: '4 feet',
colour: 'black',
is_new: true
},
}
},
{
id: 4,
category_id: 41,
options: {
'modelName31': {
size: '8 feet',
colour: 'red',
is_new: true
},
'modelName32': {
size: '8 feet',
colour: 'red',
is_new: true
},
}
}
]
the result data structure needs to be like this:
let resultArray = [
{
id: 1,
category_id: 11,
model: 'modelName1',
size: '2 feet',
colour: 'red',
is_new: true
},
{
id: 1,
category_id: 11,
model: 'modelName2',
size: '4 feet',
colour: 'black',
is_new: true
},
{
id: 2,
category_id: 21,
model: 'modelName11',
size: '2 feet',
colour: 'white',
is_new: false
},
{
id: 2,
category_id: 21,
model: 'modelName12',
size: '4 feet',
colour: 'white',
is_new: false
},
{
id: 3,
category_id: 31,
model: 'modelName21',
size: '8 feet',
colour: 'white',
is_new: false
},
{
id: 3,
category_id: 31,
model: 'modelName22',
size: '4 feet',
colour: 'black',
is_new: true
},
{
id: 4,
category_id: 41,
model: 'modelName31',
size: '8 feet',
colour: 'red',
is_new: true
},
{
id: 4,
category_id: 41,
model: 'modelName32',
size: '8 feet',
colour: 'red',
is_new: true
},
]
This is what I have tried:
let productsData = [];
products_row
.map((product, p) => Object.entries(product.options || {})
.filter((model, i) => {
return productsData.push(
{
model: model[0],
[Object.keys(product).filter(el => delete product.options)[i]]: Object.values(product)[i],
[Object.keys(model[1] || [])[i]]: Object.values(model[1] || [])[i],
}
)
})
)
console.log(productsData)
But it returns not all data, which is expected because I can't figure out how to keep previous key-values:
[
{
model: 'modelName1',
id: 1,
size: '2 feet',
},
{
model: 'modelName2',
category_id: 11,
colour: 'black',
},
{
model: 'modelName11',
id: 2,
size: '2 feet',
},
{
model: 'modelName12',
category_id: 21,
colour: 'white',
},
{
model: 'modelName21',
id: 3,
size: '8 feet',
},
{
model: 'modelName22',
category_id: 31,
colour: 'black',
},
{
model: 'modelName31',
id: 4,
size: '8 feet',
},
{
model: 'modelName32',
category_id: 41,
colour: 'red',
},
]
I am completely stuck, any help is appreciated. Thank you.
you can use flatMap and map
What flatMap does is if the returned array of map looks like
[
[{...1},{...2}],
[{...3},{...4}]
]
it will flatten it and give
[
{...1},{...2},
{...3},{...4}
]
let products_row = [{id: 1,category_id: 11,options: {'modelName1': {size: '2 feet',colour: 'red',is_new: true},'modelName2': {size: '4 feet',colour: 'black',is_new: true},}},{id: 2,category_id: 21,options: {'modelName11': {size: '2 feet',colour: 'white',is_new: false},'modelName12': {size: '4 feet',colour: 'white',is_new: false},}},{id: 3,category_id: 31,options: {'modelName21': {size: '8 feet',colour: 'white',is_new: false},'modelName22': {size: '4 feet',colour: 'black',is_new: true},}},{id: 4,category_id: 41,options: {'modelName31': {size: '8 feet',colour: 'red',is_new: true},'modelName32': {size: '8 feet',colour: 'red',is_new: true},}}]
let x = products_row.flatMap(({options,...rest}) => Object.entries(options).map(([k,v]) => ({...v,...rest,model:k})))
console.log(x)
It is quite hard to analyze your solution and reason about your idea, so I cannot fix your code.
What you want to do is to extract options from each object and attach the rest of object, in other words you want to iterate over each option for each product row.
There are numerous ways to achieve this, you can use flatMap as #cmgchess suggested. Easier to understand is something like this:
let result = [];
products_row.forEach(({ options, ...rest }) =>
Object.values(options).forEach((b) => result.push({ ...rest, ...b })),
);

Javascript sort array by date and alphabetical order

I want it to be sorted by date and alphabet in one sort how can i do that ?
I think alphabetical order works good but date not works properly. Thanks for answers.
Data structure :
[{
productId: 21,
title: "Huawei P40 Lite ",
brand: "Huawei",
price: 120,
discountPercentage: 10,
color: "Black",
createdDate: "2021-01-15T01:00:00+03:00",
},
{
productId: 22,
title: "Huawei P40 Lite",
brand: "Huawei",
price: 1026,
discountPercentage: 0,
color: "Green",
createdDate: "2021-01-16T01:00:00+03:00",
},
{
productId: 23,
title: "Apple iPhone 11",
brand: "Apple",
price: 1220,
discountPercentage: 11,
color: "White",
createdDate: "2021-01-17T01:00:00+03:00",
},
{
productId: 24,
title: "Apple iPhone 12",
brand: "Apple",
price: 1420,
discountPercentage: 11,
color: "White",
createdDate: "2021-01-18T01:00:00+03:00",
}],
Here my work :
jsfiddle.net/pazyqb01/
And tried different solutions for sort date somehow i couldn't make it work.
Sorted Array shoul be like above :
{
productId: 24,
title: "Apple iPhone 12",
brand: "Apple",
price: 1420,
discountPercentage: 11,
color: "White",
createdDate: "2021-01-18T01:00:00+03:00",
},
{
productId: 23,
title: "Apple iPhone 11",
brand: "Apple",
price: 1220,
discountPercentage: 11,
color: "White",
createdDate: "2021-01-17T01:00:00+03:00",
},
{
productId: 22,
title: "Huawei P40 Lite",
brand: "Huawei",
price: 1026,
discountPercentage: 0,
color: "Green",
createdDate: "2021-01-16T01:00:00+03:00",
},
{
productId: 21,
title: "Huawei P40 Lite ",
brand: "Huawei",
price: 120,
discountPercentage: 10,
color: "Black",
createdDate: "2021-01-15T01:00:00+03:00",
},
this way:
simply follow the list of your sorting criteria
const data =
[ { productId: 21, title: 'Huawei P40 Lite ', brand: 'Huawei', price: 120, discountPercentage: 10, color: 'Black', createdDate: '2021-01-15T01:00:00+03:00' }
, { productId: 22, title: 'Huawei P40 Lite', brand: 'Huawei', price: 1026, discountPercentage: 0, color: 'Green', createdDate: '2021-01-16T01:00:00+03:00' }
, { productId: 23, title: 'Apple iPhone 11', brand: 'Apple', price: 1220, discountPercentage: 11, color: 'White', createdDate: '2021-01-17T01:00:00+03:00' }
, { productId: 24, title: 'Apple iPhone 12', brand: 'Apple', price: 1420, discountPercentage: 11, color: 'White', createdDate: '2021-01-18T01:00:00+03:00' }
]
const fSort = (a,b) =>
{
let Dx = new Date(b.createdDate) - new Date(a.createdDate) // 1st criteria
if (Dx===0) Dx = a.title.trim().localeCompare(b.title.trim()) // 2nd
// if (Dx===0) Dx = ... // 3rd
// if (Dx===0) Dx = ... // 4th....
return Dx
}
console.log( data.sort(fSort))

highchart sankey doesn't show in vuejs

I'm using highcharts in vuejs with highcharts-vue but a sankey diagram won't show up at all:
in my main.js I have done all necessary imports
import Highcharts from 'highcharts'
import HighchartsVue from 'highcharts-vue'
import sanKeyInit from 'highcharts/modules/sankey'
sanKeyInit(Highcharts)
import exportingInit from 'highcharts/modules/exporting'
import exportDataInit from 'highcharts/modules/export-data'
import More from 'highcharts/highcharts-more'
exportingInit(Highcharts)
exportDataInit(Highcharts)
import dependencyWheelInit from 'highcharts/modules/dependency-wheel'
dependencyWheelInit(Highcharts)
treemapInit(Highcharts)
More(Highcharts)
in my vue component I can display a treemap but not the sankey diagram
Overview.vue
<template>
<v-container pa-0 ma-0>
<v-layout column>
<v-flex xs12>
<v-container pa-0 ma-0 >
<KeyValue :value="breadCrumb.join('>')" label=""></KeyValue>
</v-container>
</v-flex>
<v-layout row>
<v-flex xs12>
<v-layout row>
<v-flex xs6>
<highcharts :constructor-type="'chart'" :options="treeMap" :callback="initMap" ref="treeMap"></highcharts>
</v-flex>
<v-flex xs6>
<!-- <highcharts :constructor-type="'chart'" :options="arc" :callback="initCircles" ref="circle"></highcharts> -->
<highcharts :constructor-type="'chart'" :options="wheel" :callback="initWheel">
</highcharts>
</v-flex>
</v-layout>
</v-flex>
</v-layout>
</v-layout>
</v-container>
</template>
<script>
import vue from 'vue'
import KeyValue from '#/components/KeyValue'
export default {
name: 'Overview',
components: {
KeyValue
},
data(){
return {
breadCrumb: [this.rootName],
hashTree: {},
charts: {treemap: null, circles: null, wheel: null},
currentGraph: {nodeList: [], linkList: []},
tree: [
{name: 'thesponge', id: '2', value: 12, color: '#aaa'},
{name: 'aa', id: '3', parent: '2', value: 34, color: '#aaa'},
{name: 'ab', id: '4', parent: '2', value: 20, color: '#aaa'},
{name: 'bob ', id: '5', value: 45, color: '#a00'},
{name: 'ba', id: '6', parent: '5', value: 40, color: 'red'},
{name: 'bb', id: '7', parent: '5', value: 56, color: 'red'},
{name: 'bba', id: '8', parent: '5', value: 40, color: 'red'},
{name: 'bbb', id: '9', parent: '5', value: 56, color: 'red'},
{name: 'bba', id: '10', parent: '8', value: 40, color: 'red'},
{name: 'bbb', id: '11', parent: '8', value: 56, color: 'red'},
],
arch: { '2': { nodeList: [{key: 'a', category: 'OfActivity', text: 'hello' },
{key: 'ab', category: 'OfActivity', text: 'goodbye' }],
linkList: [{from: {nodeIdInCurrentGraph: 'a'}, to: {nodeIdInCurrentGraph: 'ab'}},
{from: {nodeIdInCurrentGraph: 'ab'}, to: {nodeIdInCurrentGraph: 'ac'}}
]
},
'': { nodeList: [{key: 'a', category: 'OfActivity', text: 'miles' },
{key: 'ab', category: 'OfActivity', text: 'davis' }],
linkList: [{from: {nodeIdInCurrentGraph: 'a'}, to: {nodeIdInCurrentGraph: 'ab'}},
{from: {nodeIdInCurrentGraph: 'a'}, to: {nodeIdInCurrentGraph: 'ac'}}
]
},
'5': { nodeList: [{key: 'a', category: 'OfActivity', text: 'john' },
{key: 'ab', category: 'OfActivity', text: 'doe' }],
linkList: [{from: {nodeIdInCurrentGraph: 'a'}, to: {nodeIdInCurrentGraph: 'ab'}},
{from: {nodeIdInCurrentGraph: 'a'}, to: {nodeIdInCurrentGraph: 'a'}},
{from: {nodeIdInCurrentGraph: 'ac'}, to: {nodeIdInCurrentGraph: 'ab'}},]
}
}
}
},
computed: {
wheel(){
return {
title: { text: 'Dependencies' },
chart: {
type: 'chart'
},
series: [{
visible: true,
name: 'country deps',
keys: ['from', 'to', 'wheight'],
/* data:[ this.arch[''].linkList.map((l)=>{return {from: l.from.nodeIdInCurrentGraph, to: l.to.nodeIdInCurrentGraph, weight: 1}})
* ],*/
data: [ ['Brazil', 'Portugal', 5],
['Brazil', 'France', 1],
['Brazil', 'Spain', 1],
['Brazil', 'England', 1],
['Canada', 'Portugal', 1],
['Canada', 'France', 5],
['Canada', 'England', 1],
['Mexico', 'Portugal', 1],
['Mexico', 'France', 1],
['Mexico', 'Spain', 5],
['Mexico', 'England', 1],
['USA', 'Portugal', 1],
['USA', 'France', 1],
['USA', 'Spain', 1],
['USA', 'England', 5],
['Portugal', 'Angola', 2],
['Portugal', 'Senegal', 1],
['Portugal', 'Morocco', 1],
['Portugal', 'South Africa', 3],
['France', 'Angola', 1],
['France', 'Senegal', 3]
],
type: 'sankey',
}]
}
},
// ---
treeMap() {
return {
title: { text: 'Navigate' },
chart: {
events: {
load(){
this.__proto__.vue.initTreeSeries()
}
},
},
series: [{
type: 'treemap',
layoutAlgorithm: 'squarified',
allowDrillToNode: true,
animationLimit: 1000,
dataLabels: {
enabled: false
},
levelIsConstant: false,
levels: [{
level: 1,
dataLabels: {
enabled: true
},
borderWidth: 3
}],
events: {
setRootNode(){
this.chart.__proto__.vue.updateCharts(arguments[0])
}
},
data: []
}]
}
},
}
},
props: {
rootName: {type: String, default: 'root'},
width: {type: Number, default: 500},
height: {type: Number, default: 500}
},
methods: {
initWheel(chart){
console.log("init wheel", chart)
chart.__proto__.vue = this
this.charts.wheel = chart
},
initMap(chart){
this.hashTree = this.tree.reduce((mem,n)=>{
n.children = []
if(!n.parent) n.parent = ''
mem[n.id] = n
return mem
},{})
this.tree.forEach((n)=>{
if(n.parent === '') return
if(!this.hashTree[n.parent]) return
this.hashTree[n.parent].children.push(n)
})
chart.__proto__.vue = this
this.charts.treemap = chart
}
}
}
</script>
result of sankey diagram in vuejs
Although the treemap shows properly, the sankey diagram doesn't
I've used the highchart debugger and yet no error.
Please help !!!
thanks

How to sort array by property in Javascript [duplicate]

This question already has answers here:
sorting object Sunday to Saturday in javascript
(2 answers)
Closed 2 years ago.
I have a array as bellow:
const list = [
{ id: 1, name: 'Product 1', color: 'white'},
{ id: 2, name: 'Product 2', color: 'black'},
{ id: 3, name: 'Product 3', color: 'red'},
{ id: 4, name: 'Product 4', color: 'white'},
{ id: 5, name: 'Product 5', color: 'black'},
]
I want to sort array based on predefined order by color: red -> white -> black and output:
const list = [
{ id: 3, name: 'Product 3', color: 'red'},
{ id: 1, name: 'Product 1', color: 'white'},
{ id: 4, name: 'Product 4', color: 'white'},
{ id: 5, name: 'Product 5', color: 'black'},
{ id: 2, name: 'Product 2', color: 'black'}
]
let colorPriority = ['red', 'white', 'black'];
list = list.sort((obj1, obj2) => colorPriority.indexOf(obj1.color) - colorPriority.indexOf(obj2.color));
this code should work for you.

highcharts - How to sort xAxis category by total?

Is there a way to order this highchart chart by total?
https://jsfiddle.net/bsvLnnxv/3/
The final result expected in this case should be:
Name 1 -> 19
Name 4 -> 12
Name 3 -> 10
Name 2 -> 8
Find the code below:
$(function () {
$('#container').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
type: 'category'
},
yAxis: {
min: 0,
title: {
text: 'Highchart test'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold'
}
}
},
legend: {
enabled: true
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series: [{
name: 'AAA',
data: [{
name: 'Name 1',
y: 5,
drilldown: 'Name1AAA'
}, {
name: 'Name 2',
y: 2
}, {
name: 'Name 3',
y: 2
}]
}, {
name: 'BBB',
data: [{
name: 'Name 1',
y: 10,
drilldown: 'Name1BBB'
}, {
name: 'Name 2',
y: 5
}]
}, {
name: 'CCC',
data: [{
name: 'Name 4',
y: 12
}, {
name: 'Name 3',
y: 8
}, {
name: 'Name 1',
y: 4,
drilldown: 'Name1CCC'
}, {
name: 'Name 2',
y: 1
}]
}],
drilldown: {
series: [{
name: 'Name 1 - AAA',
id: 'Name1AAA',
data: [
['Name 1/1', 2],
['Name 1/2', 2],
['Name 1/3', 1],
]
}, {
name: 'Name 1 - BBB',
id: 'Name1BBB',
data: [
['Name 1/1', 7],
['Name 1/2', 2],
['Name 1/3', 1],
]
}, {
name: 'Name 1 - CCC',
id: 'Name1CCC',
data: [
['Name 1/1', 2],
['Name 1/2', 3],
['Name 1/3', 4],
]
}]
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="http://github.highcharts.com/modules/drilldown.js"></script>
<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>
I found the solution!
Highcharts doesn't have a property to sort the data automatically, so you must fill all series data previously sorted.
Another point of attention: if you don't have a value you will need to set the value as 0 to make sure that all categories have the same quantity of elements.
https://jsfiddle.net/bsvLnnxv/4/
$(function () {
$('#container').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
type: 'category'
},
yAxis: {
min: 0,
title: {
text: 'Highchart test'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold'
}
}
},
legend: {
enabled: true
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series: [{
name: 'AAA',
data: [{
name: 'Name 1',
y: 5,
drilldown: 'Name1AAA'
}, {
name: 'Name 4',
y: 0
}, {
name: 'Name 3',
y: 2
}, {
name: 'Name 2',
y: 2
}]
}, {
name: 'BBB',
data: [{
name: 'Name 1',
y: 10,
drilldown: 'Name1BBB'
}, {
name: 'Name 4',
y: 0
}, {
name: 'Name 3',
y: 0
}, {
name: 'Name 2',
y: 5
}]
}, {
name: 'CCC',
data: [{
name: 'Name 1',
y: 4,
drilldown: 'Name1CCC'
}, {
name: 'Name 4',
y: 12
}, {
name: 'Name 3',
y: 8
}, {
name: 'Name 2',
y: 1
}]
}],
drilldown: {
series: [{
name: 'Name 1 - AAA',
id: 'Name1AAA',
data: [
['Name 1/1', 2],
['Name 1/2', 2],
['Name 1/3', 1],
]
}, {
name: 'Name 1 - BBB',
id: 'Name1BBB',
data: [
['Name 1/1', 7],
['Name 1/2', 2],
['Name 1/3', 1],
]
}, {
name: 'Name 1 - CCC',
id: 'Name1CCC',
data: [
['Name 1/1', 2],
['Name 1/2', 3],
['Name 1/3', 4],
]
}]
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="http://github.highcharts.com/modules/drilldown.js"></script>
<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>

Categories