I'm trying to obtain a list from a list in Javascript.
This is the list:
const cars = [
{
id: 1,
brand: "Mercedes Benz",
properties: [
{
property: "Mechanical",
value: 2,
},
{
property: "Chemical",
value: 2,
},
{
property: "Pressure",
value: 3,
}],
},
{
id: 2,
brand: "BMW",
properties: [
{
property: "Mechanical",
value: 5,
},
{
property: "Chemical",
value: 3,
},
{
property: "Pressure",
value: 6,
}],
}
]
I need the cars which have a determined property with a value greater than X
For example, if I say that the property is Mechanical and the value is 3 I'll obtain the complete object with id 2
Does anyone have an idea? That is having me a hard time
Sorry for the bad formatting of the code, StackOverflow is not letting post it formatted for some reason.
Tip: I paste it on a Node REPL ;)
Thanks in advance
Use filter:
const desiredProp = "Mechanical";
const minVal = 3;
const filteredCars = cars.filter(car =>
car.properties.some(
prop => prop.property === desiredProp && prop.value >= minVal
)
);
If you're only looking for the first match and not an array of all matches, replace filter with find.
You can create a propGreaterThan function that takes the desired property and the number that you need it to be greater then. Using a combination of filter on the cars array and find on the properties array, you can find the appropriate cars.
const cars = [
{
id: 1,
brand: "Mercedes Benz",
properties: [
{
property: "Mechanical",
value: 2,
},
{
property: "Chemical",
value: 2,
},
{
property: "Pressure",
value: 3,
}],
},
{
id: 2,
brand: "BMW",
properties: [
{
property: "Mechanical",
value: 5,
},
{
property: "Chemical",
value: 3,
},
{
property: "Pressure",
value: 6,
}],
}
]
function propGreaterThan(prop, num) {
return cars.filter(car => {
return car.properties.find(p => p.property === prop).value > num;
});
}
console.log(
propGreaterThan("Chemical", 2)
)
Related
I got an array and want to convert my array into new shape, something like what on html section, so I did it successfully, but there is a problem, and a question:
Question: can I use iteration once? I mean already used map with filter, is there a better way to do this? like use single function like filter or reduce without map ?
Problem: I want to change id key name to value and title to label, but looks like can't do this in filter() Also I used forEach and map and reduce and etc.. but didn't work.
let data = [{
id: 1,
group: 1,
parent: 1,
title: 'group a'
}, {
id: 2,
group: 1,
parent: null,
title: 'a1'
}, {
id: 3,
group: 1,
parent: null,
title: 'a2'
}, {
id: 4,
group: 2,
parent: null,
title: 'b1'
},
{
id: 5,
group: 2,
parent: 2,
title: 'group b'
}
];
let array = [];
data.map(function(item) {
if (item.parent) {
let obj = {};
obj.label = item.title
//obj.options = data.filter(x => !x.parent && x.group === item.parent);
obj.options = data.map(x => !x.parent && x.group === item.parent ? {value: x.id, label: x.title} : {});
array.push(obj)
}
})
console.log(array);
<script>
[{
label: "group a",
options: [{
label: "a1",
value: 1
},
{
label: "a2",
value: 2
}
]
},
{
label: "group b",
options: [{
label: "b1",
value: 4
}
]
}];
</script>
I tried this, and used short if condition but it will add empty object if condition is false:
obj.options = data.map(x => !x.parent && x.group === item.parent ? {value: x.id, label: x.title} : {});
Your solution is not the ideal way to do this but if tweaked a little it can still be made to work. Just put a filter after your map condition to remove all the empty objects.
let data = [{
id: 1,
group: 1,
parent: 1,
title: 'group a'
}, {
id: 2,
group: 1,
parent: null,
title: 'a1'
}, {
id: 3,
group: 1,
parent: null,
title: 'a2'
}, {
id: 4,
group: 2,
parent: null,
title: 'b1'
},
{
id: 5,
group: 2,
parent: 2,
title: 'group b'
}
];
let array = [];
data.forEach(function(item) {
if (item.parent) {
let obj = {};
obj.label = item.title
obj.options = data.map(x => !x.parent && x.group === item.parent ? {value: x.id, label: x.title} : {}).filter(x => Object.keys(x).length > 0);
array.push(obj)
}
})
console.log(array);
<script>
[{
label: "group a",
options: [{
label: "a1",
value: 1
},
{
label: "a2",
value: 2
}
]
},
{
label: "group b",
options: [{
label: "b1",
value: 4
}
]
}];
</script>
I have used Object.keys.
Also map is when you want to transform the array into a new one. map returns an array, if you are not making use of the returned array, then map is not the ideal choice. That is why I used forEach.
Note:. The way to do this properly would be .reduce(). It is for computing a result from an array, where at each iteration you can refer to the accumulated object uptil that iteration.
Situation is simple: Make a double map to deconstruct into a single Array rather then multiple.
The Data example:
const data = [
{
name: 'testa',
values: [
{ index: '1993', value: 5 },
{ index: '1994', value: 6 },
],
},
{
name: 'testb',
values: [
{ index: '1991', value: 8 },
{ index: '1992', value: 3 },
{ index: '1993', value: 9 },
],
},
];
A method should take this array and convert into a single array of this data (order dosent matter):
const proccessedData = [
{ index: '1993', value: 5, name: 'testa' },
{ index: '1994', value: 6, name: 'testa' },
{ index: '1991', value: 8, name: 'testb' },
{ index: '1992', value: 3, name: 'testb' },
{ index: '1993', value: 9, name: 'testb' },
];
I achieve this by using this method I created:
const getData = (obj) => {
const data = [];
obj.map(({ values, name }) => {
data.push(...values.map(({ index, value }) => ({ index, value, name })));
});
return data;
};
And it works BUT I disliake it because of (read below in The Problem):
THE PROBLEM
It depends on const data = [] to do a data.push(...). Would prefer that it would auto decontruct it so a method would look something like this:
const getData = (obj) =>
obj.map(({ values, name }) => values.map(({ index, value }) => ({ index, value, name })));
Basically, on a single line, without the use of another variable BUT the return structure would remain as mentioned above. But using thtis method it returns an array with 2 different arrays inside.
It is being used inside another structure like so:
const config = {
data: getData(data),
height: 400,
xField: "index",
yField: "value",
seriesField: "name"
};
So it has to return deconstructed array already without involving any other variables. Yes, I could leave it as it is right now, but I wanna do the deconstruction way as its cleaner, in my opinion, and I would learn something new.
NOTE doing data: {...getData(data)}, or data: [...getData(data)], does Not work.
A working example to play around: https://codesandbox.io/s/bold-cannon-fwot6?file=/src/App.js:690-826
This would be simpler with flatMap:
const data = [
{
name: 'testa',
values: [
{ index: '1993', value: 5 },
{ index: '1994', value: 6 },
],
},
{
name: 'testb',
values: [
{ index: '1991', value: 8 },
{ index: '1992', value: 3 },
{ index: '1993', value: 9 },
],
},
];
proccessedData = data.flatMap(d => d.values.map(v => ({...v, name: d.name})))
console.log(proccessedData)
You can also try this: I am using here map function twice, and then flatten into a single array, The flatMap method is identical to a map followed by a call to a flat of depth 1.
const data = [
{
name: 'testa',
values: [
{ index: '1993', value: 5 },
{ index: '1994', value: 6 },
],
},
{
name: 'testb',
values: [
{ index: '1991', value: 8 },
{ index: '1992', value: 3 },
{ index: '1993', value: 9 },
],
},
];
const dataProcess = data
.map((d) =>
d.values.map((v) => ({...v, name: d.name}))
).flat();
console.log(dataProcess);
Is there any quick way to remove a specific object from an object array, filtering by a key and value pair, without specifying an index number?
For example, if there was an object array like so:
const arr = [
{ id: 1, name: 'apple' },
{ id: 2, name: 'banana' },
{ id: 3, name: 'cherry' },
...,
{ id: 30, name: 'grape' },
...,
{ id: 50, name: 'pineapple' }
]
How can you remove only the fruit which has the id: 30 without using its index number?
I have already figured out one way like the following code, but it looks like a roundabout way:
for ( let i = 0; i < arr.length; i++) {
if ( arr[i].id === 30 ) {
arr.splice(i, 1);
}
}
with es6 standard, you can use the filter method
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
const arr = [
{ id: 1, name: 'apple' },
{ id: 2, name: 'banana' },
{ id: 3, name: 'cherry' },
{ id: 30, name: 'grape' },
{ id: 50, name: 'pineapple' }
];
// !== for strict checking
console.log(arr.filter(e => e.id !== 30))
I have an array of objects and Im trying to filter by matching ids
//Vehicle is added to quote
function filterByID(item) {
return item.id === 1;
}
this.vehicle = this.data.filter(filterByID);
data is as follows:
data: [
0: {
id: 0,
name: name
},
1: {
id: 1,
name: name
},
2: {
id: 2,
name: name
}
]
Im getting an empty error when I check the vehicle part
Are you using it like this:
const data = [
{
id: 0,
name: '',
},
{
id: 1,
name: '',
},
{
id: 2,
name: '',
},
];
function filterByID(item) {
return item.id === 1;
}
console.log(data.filter(filterByID)); // output: [{ "id": 1, "name": "" }]
You don't always need to define a separate function, you can use an arrow function, as below.
const data = [{
id: 0,
name: name
},
{
id: 1,
name: name
},
{
id: 2,
name: name
}
]
const vehicle = data.filter(item => item.id === 1);
console.log(vehicle);
This works fine in pure JS, it looks like it might be an issue with the lifecycle or state of your application. Use console.log to make sure that this.data is what you expect it to be
I have 2 arrays:
0: {id: 2, name: "TMA"}
1: {id: 3, name: "Hibbernate"}
0: {id: 1, name: "FB.DE"}
1: {id: 2, name: "TMA"}
2: {id: 3, name: "Hibbernate"}
3: {id: 4, name: "Event.it A"}
4: {id: 5, name: "Projket 2"}
5: {id: 6, name: "Projekt 1"}
I want to compare them and delete the objects with the id 2 and 3 cause both arrays have them and thats the similarity.
This is my Code so far:
const projectListOutput = projectsOfPersonArray.filter(project => data.includes(project));
console.log(projectListOutput);
But every time i run this projectListOutput is empty.
When using includes dont compare objects, Just build data as array of strings. Remaining code is similar to what you have.
arr1 = [
{ id: 2, name: "TMA" },
{ id: 3, name: "Hibbernate" },
];
arr2 = [
{ id: 1, name: "FB.DE" },
{ id: 2, name: "TMA" },
{ id: 3, name: "Hibbernate" },
{ id: 4, name: "Event.it A" },
{ id: 5, name: "Projket 2" },
{ id: 6, name: "Projekt 1" },
];
const data = arr1.map(({ id }) => id);
const result = arr2.filter(({ id }) => !data.includes(id));
console.log(result);
Your data array probably does not contain the exact same object references than projectsOfPersonArray. Look at the code below:
[{ foo: 'bar' }].includes({ foo: 'bar' });
// false
Objects look equal, but they don't share the same reference (= they're not the same).
It's safer to use includes with primitive values like numbers or strings. You can for example check the ids of your objects instead of the full objects.
You compare different objects, so every object is unique.
For filtering, you need to compare all properties or use a JSON string, if the order of properties is equal.
var exclude = [{ id: 2, name: "TMA" }, { id: 3, name: "Hibbernate" }],
data = [{ id: 2, name: "TMA" }, { id: 3, name: "Hibbernate" }, { id: 1, name: "FB.DE" }, { id: 2, name: "TMA" }, { id: 3, name: "Hibbernate" }, { id: 4, name: "Event.it A" }, { id: 5, name: "Projket 2" }, { id: 6, name: "Projekt 1" }],
result = data.filter(project =>
!exclude.some(item => JSON.stringify(item) === JSON.stringify(project))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do something similar to the next:
const source = [{
id: 1,
name: "FB.DE"
},
{
id: 2,
name: "TMA"
},
{
id: 3,
name: "Hibbernate"
},
{
id: 4,
name: "Event.it A"
},
{
id: 5,
name: "Projket 2"
},
{
id: 6,
name: "Projekt 1"
}
]
const toRemove = [{
id: 2,
name: "TMA"
},
{
id: 3,
name: "Hibbernate"
}
]
/**create object where keys is object "id" prop, and value is true**/
const toRemoveMap = toRemove.reduce((result, item) => ({
...result,
[item.id]: true
}), {})
const result = source.filter(item => !toRemoveMap[item.id])
You can make function from it:
function removeArrayDuplicates (sourceArray, duplicatesArray, accessor) {
const toRemoveMap = duplicatesArray.reduce((result, item) => ({
...result,
[item[accessor]]: true
}), {});
return sourceArray.filter(item => !toRemoveMap[item[accessor]])
}
removeArrayDuplicates(source, toRemove, 'id')
Or even better, you can make it work with a function instead of just property accessor:
function removeDuplicates (sourceArray, duplicatesArray, accessor) {
let objectSerializer = obj => obj[accessor];
if(typeof accessor === 'function') {
objectSerializer = accessor;
}
const toRemoveMap = duplicatesArray.reduce((result, item) => ({
...result,
[objectSerializer(item)]: true
}), {});
return sourceArray.filter(item => !toRemoveMap[objectSerializer(item)])
}
removeDuplicates(source, toRemove, (obj) => JSON.stringify(obj))
This function will help you merge two sorted arrays
var arr1 = [
{ id: 2, name: 'TMA' },
{ id: 3, name: 'Hibbernate' },
]
var arr2 = [
{ id: 1, name: 'FB.DE' },
{ id: 2, name: 'TMA' },
{ id: 3, name: 'Hibbernate' },
{ id: 4, name: 'Event.it A' },
{ id: 5, name: 'Projket 2' },
]
function mergeArray(array1, array2) {
var result = []
var firstArrayLen = array1.length
var secondArrayLen = array2.length
var i = 0 // index for first array
var j = 0 // index for second array
while (i < firstArrayLen || j < secondArrayLen) {
if (i === firstArrayLen) { // first array doesn't have any other members
while (j < secondArrayLen) { // we copy rest members of first array as a result
result.push(array2[j])
j++
}
} else if (j === secondArrayLen) { // second array doesn't have any other members
while (i < firstArrayLen) { // we copy the rest members of the first array to the result array
result.push(array1[i])
i++
}
} else if (array1[i].id < array2[j].id) {
result.push(array1[i])
i++
} else if (array1[i].id > array2[j].id) {
result.push(array2[j])
j++
} else {
result.push(array1[i])
i++
j++
}
}
return result
}
console.log(mergeArray(arr1,arr2));