Related
This question already has answers here:
Merge two array of objects based on a key
(23 answers)
Closed 4 months ago.
I have 2 different arrays, that i want to combine.
The first one looks like following:
const Cats[] = [
{ id: '1', name: 'Smiley' },
{ id: '2', name: 'Purple' },
]
the second one:
const catAges[] = [
{ id: '4', age: '13', catId: '1' },
{ id: '5', age: '4', catId: '2' },
];
and i want to combine them where id from Cats[] and catId from catAges[] are the same and have a result like following:
{ id: '4', age: '13', cat: { id: '1', name: 'Smiley' } },
{ id: '5', age: '4', cat: { id: '2', name: 'Purple' } },
i get the arrays from 2 different async functions looking like this:
const cats = [await getByCatId("1"), await getByCatId("2")];
const catsAge = await getCatsAges();
But i need help in how i combine these 2 and map them. I've tried something like this but without any success:
const all = (cats, catsAge) =>
cats.map(cats=> ({
...catsAge.find((cats) => (catsAge.catId === cats.id) && catsAge),
...cats
}));
console.log(all(cats, catsAge));
Thankful for any help in how to move forward.
const Cats = [
{ id: '1', name: 'Smiley' },
{ id: '2', name: 'Purple' },
]
const catAges = [
{ id: '4', age: '13', catId: '1' },
{ id: '5', age: '4', catId: '2' },
];
const transformed = catAges.map(item => {
const cat = Cats.find(cat => cat.id === item.catId);
if (cat) {
item.cat = cat;
delete item.catId;
}
return item;
});
console.log(transformed);
The problem with your function is just that you're re-using the cats variable too much, so in your .find comparision you're comparing an element from catsAge (as cats.id) and the catsAge array (as catsAge.catId) which is undefined.
Try this:
const all = (cats, catsAge) =>
cats.map((cat) => ({
...catsAge.find((catsAge) => catsAge.catId === cat.id),
...cat,
}));
Pro tip: Learn+Use Typescript and the compiler would catch these errors for you :)
const Cats = [
{ id: '1', name: 'Smiley' },
{ id: '2', name: 'Purple' },
]
const catAges = [
{ id: '4', age: '13', catId: '1' },
{ id: '5', age: '4', catId: '2' },
];
catAges.map(catage => {
const cat = Cats.find(c => c.id == catage.catId);
if(cat) {
delete catage.catId;
catage.cat = cat;
return catage;
}
});
I have two arrays which is an array of different animals and an array of name of animals. I want to make animal buttons and each animal buttons have its own color depending on what kind of animal they are.
I was using map functions but it didn't really worked.
export const animalColors = [
{
color: '#FF6800',
name: 'lion',
},
{
color: '#D80C18',
name: 'panda',
},
{
color: '#FF8A3D',
name: 'tiger',
},
{
color: '#02C75A',
name: 'rabbit',
},
{
color: '#608DF9',
name: 'bear',
},
{
color: '#0584F6',
name: 'elephant',
},
{
color: '#222F3E',
name: 'deer',
},
{
color: '#727272',
name: 'bird',
},
{
color: '#656598',
name: 'turtle',
},
];
const zoo = [
{ id: '1', name: 'lion' },
{ id: '2', name: 'panda' },
{ id: '3', name: 'tiger' },
{ id: '4', name: 'rabbit' },
{ id: '5', name: 'bear' },
{ id: '6', name: 'elephant' },
{ id: '7', name: 'deer' },
{ id: '8', name: 'bird' },
{ id: '9', name: 'turtle' },
]
These are the codes of typescript right below.
The data.docs is the array called zoo.
const BoardItemCard = ({ data }: BoardItemCardProps) => {
return (
<div className="BoardItemCard">
{data &&
data.docs.map((item: Item, i: number) => {
return (
<button style={{backgroundColor: ????}}>
{item.name}
</button>
)
You can use array.find() to get corresponding color:
<button style={{backgroundColor: animalColors.find(x => x.name === item.name)?.color || 'defaultColor'}}>
{item.name}
</button>
Just using the Array iteration methods built into JS is fine for this:
var result1 = [
{id:1, name:'Sandra', type:'user', username:'sandra'},
{id:2, name:'John', type:'admin', username:'johnny2'},
{id:3, name:'Peter', type:'user', username:'pete'},
{id:4, name:'Bobby', type:'user', username:'be_bob'}
];
var result2 = [
{id:2, name:'John', email:'johnny#example.com'},
{id:4, name:'Bobby', email:'bobby#example.com'}
];
var props = ['id', 'name'];
var result = result1.filter(function(o1){
// filter out (!) items in result2
return !result2.some(function(o2){
return o1.id === o2.id; // assumes unique id
});
}).map(function(o){
// use reduce to make objects with only the required properties
// and map to apply this to the filtered array as a whole
return props.reduce(function(newo, name){
newo[name] = o[name];
return newo;
}, {});
});
document.body.innerHTML = '<pre>' + JSON.stringify(result, null, 4) +
'</pre>';
I'm trying to make a filter. The number of filters will change dynamically, a number of keys can be different, and the number of values, too.
This is how data look like:
var data = [
{id: "123", color: "Red", model: "Tesla"},
{id: "124", color: "Black", model: "Honda"},
{id: "125", color: "Red", model: "Audi"},
{id: "126", color: "Blue", model: "Tesla"}]
Filter keys are color and model. But sometimes I will filter only by color or model and sometimes by both. I want to make a function that will cover both cases. Also, a user can choose many values (Tesla, Honda...).
Key can be only color, or only model, or both.
Values can look like: only "Red", "Red" and "Blue", or "Red" and "Tesla", or "Red", "Blue" and "Tesla"... Depends on what user choose.
I tried this:
var filtered = [];
data.forEach(item => {
filterByKey.forEach(key => {
values.forEach(value => {
if (item[key] === value) {
filtered.push(item);
}
});
});
});
Here is JsFiddle
My loop works well when I have one filter key, but it doesn't work well when I have more than one key. Is it a good idea to pass keys and values as an array?
No jQuery please, only pure JavaScript.
You can use filter() with every() and check if value of current object with current key exits in values array using includes()
var data = [{"id":"123","color":"Red","model":"Tesla"},{"id":"124","color":"Black","model":"Honda"},{"id":"125","color":"Red","model":"Audi"},{"id":"126","color":"Blue","model":"Tesla"}]
var keys = ["color", 'model'];
var values = ["Tesla", "Audi", "Red"];
var result = data.filter(function(e) {
return keys.every(function(a) {
return values.includes(e[a])
})
})
console.log(result);
You could use a combined approach with a seach object which keeps the conditions, like
{
model: 'Tesla', // a single value
color: ['red', 'blue'], // a some value
price: { // a range/interval
min: 2000,
max: 3000
},
transmission: v => v.toLowerCase() === 'automatic' // a function
}
var useConditions = search => a => Object.keys(search).every(k =>
a[k] === search[k] ||
Array.isArray(search[k]) && search[k].includes(a[k]) ||
typeof search[k] === 'object' && +search[k].min <= a[k] && a[k] <= +search[k].max ||
typeof search[k] === 'function' && search[k](a[k])
),
data = [{ id: "123", color: "Red", model: "Tesla" }, { id: "124", color: "Black", model: "Honda" }, { id: "125", color: "Red", model: "Audi" }, { id: "126", color: "Blue", model: "Tesla" }],
filters = { color: ['Red', 'Blue'], model: 'Tesla' };
console.log(data.filter(useConditions(filters)));
You can use Array.prototype.filter() where the function to test each element of the array is:
el => !!filterBy.toString().match(new RegExp(`(?=.*${el.color})(?=.*${el.model})`))
It consist of a regular expression new RegExp(`(?=.*${el.color})(?=.*${el.model})`)) that match to strings color and model in another string filterBy.toString()
var data = [{id: "123", color: "Red", model: "Tesla"}, {id: "124", color: "Black", model: "Honda"}, {id: "125", color: "Red", model: "Audi"}, {id: "126", color: "Blue", model: "Tesla"}],
filterBy = ['Tesla', 'Audi', 'Red', 'Black'],
result = data.filter(el => !!filterBy.toString().match(new RegExp(`(?=.*${el.color})(?=.*${el.model})`)));
console.log(result);
And also, you can combine Array.prototype.filter() and Array.prototype.includes():
var data = [{id: "123", color: "Red", model: "Tesla"}, {id: "124", color: "Black", model: "Honda"}, {id: "125", color: "Red", model: "Audi"}, {id: "126", color: "Blue", model: "Tesla"}],
filterBy = ['Tesla', 'Audi', 'Red', 'Black'],
result = data.filter(el => filterBy.includes(el.model) && filterBy.includes(el.color));
console.log(result);
For a case like this here's what I just do:
function _filter(data, query) { // query = "Red" or "Tesla"
return data.filter(el => {
return el.model.toLowerCase().indexOf(query.toLowerCase()) !== -1 ||
el.name.toLowerCase().indexOf(query.toLowerCase()) !== -1;
});
}
Now this function searches data on the model key and name key.
Is this what you want to achieve?
var data = [
{id: "123", color: "Red", model: "Tesla"},
{id: "124", color: "Black", model: "Honda"},
{id: "125", color: "Red", model: "Audi"},
{id: "126", color: "Blue", model: "Tesla"}
];
var allowedColors = ["Red", "Blue"];
var allowedModels = ["Tesla", "Audi"];
function filter (cars, colors, models) {
return cars.filter(function (car) {
return colors.indexOf(car.color) !== -1 && // check if the car's color is allowed
models.indexOf(car.model) !== -1; // check if the car's model is allowed
});
}
var filtered = filter(data, allowedColors, allowedModels);
console.log(filtered);
Filtering is native in JS, try this:
data.filter(item => item.color==='Red');
// or in the old fashion
data.filter(function(item){ return item.color==='Red';} );
Here, I have a different scenario.
I have an object
d={r1: {name: "r1", validation: true}, r2: {name: "r2", validation: true}};
and another array
a = ["r1"];
Here, the result I want is
d={r1: {name: "r1", validation: true}}
Using filter() to filter data, combined with some() to check if multiple keys match at least one of the strings from the values using includes()
// array --------------------
const data = [
{ id: '123', color: 'Red', model: 'Tesla' },
{ id: '124', color: 'Black', model: 'Honda' },
{ id: '125', color: 'Red', model: 'Audi' },
{ id: '126', color: 'Blue', model: 'Tesla' },
];
// filter exact match --------------------
const keysExact = ['color', 'model'];
const valuesExact = ['Tesla', 'Audi', 'Red'];
const resultExact = data.filter((item) =>
keysExact.every((a) => valuesExact.includes(item[a]))
);
console.log(resultExact);
// result:
// [
// { id: '123', color: 'Red', model: 'Tesla' },
// { id: '125', color: 'Red', model: 'Audi' },
// ];
Using filter() to filter data, combined with some() to check if multiple keys contain at least one of the strings from the values using includes().
// array --------------------
const data = [
{ id: '123', color: 'Red', model: 'Tesla' },
{ id: '124', color: 'Black', model: 'Honda' },
{ id: '125', color: 'Red', model: 'Audi' },
{ id: '126', color: 'Blue', model: 'Tesla' },
];
// filter data by keys containing values string (at least one of the string in values) --------------------
const keysSome = ['color', 'model'];
const valuesSome = ['Tes', 're'];
const resultSome = data.filter((item) =>
keysSome.some((key) =>
valuesSome.some((val) => item[key].toLowerCase().includes(val.toLowerCase()))
)
);
console.log(resultSome);
// result:
// [
// { id: '123', color: 'Red', model: 'Tesla' },
// { id: '125', color: 'Red', model: 'Audi' },
// { id: '126', color: 'Blue', model: 'Tesla' },
// ];
Using filter() to filter data, combined with every() to check if multiple keys contain all strings from the values using includes().
// array --------------------
const data = [
{ id: '123', color: 'Red', model: 'Tesla' },
{ id: '124', color: 'Black', model: 'Honda' },
{ id: '125', color: 'Red', model: 'Audi' },
{ id: '126', color: 'Blue', model: 'Tesla' },
];
// filter data by keys containing values string (matches all strings from values) --------------------
const keysEvery = ['color', 'model'];
const valuesEvery = ['Tes', 're'];
const resultEvery = data.filter((item) =>
keysEvery.every((key) =>
valuesEvery.some((val) => item[key].toLowerCase().includes(val.toLowerCase()))
)
);
console.log(resultEvery);
// result:
// [
// { id: '123', color: 'Red', model: 'Tesla' }
// ]
I'm trying to filter this array to get the id and convert from a string to a number. I want to use filter and map? Wanting to know how to make it as clear as possible.
var pets = [
{ id: '1', name: 'rupert', readyForHome: 'No', age: 12, personality: ['friendly', 'lazy', 'loving']},
{ id: '2', name: 'mrs fluffy', readyForHome: 'Yes', age: 2, personality: ['affectionate', 'playful', 'shy']},
{ id: '3', name: 'tabitha', readyForHome: 'Yes', age: 4, personality: ['aggressive', 'independent']},
{ id: '4', name: 'lily', readyForHome: 'No', age: 8, personality: ['friendly', 'playful', 'mischievous']},
];
All you need is map to get down to an array of ids as numbers:
pets = pets.map(function(pet) {
return Number(pet.id);
});
var pets=[{id:"1",name:"rupert",readyForHome:"No",age:12,personality:["friendly","lazy","loving"]},{id:"2",name:"mrs fluffy",readyForHome:"Yes",age:2,personality:["affectionate","playful","shy"]},{id:"3",name:"tabitha",readyForHome:"Yes",age:4,personality:["aggressive","independent"]},{id:"4",name:"lily",readyForHome:"No",age:8,personality:["friendly","playful","mischievous"]}];
pets = pets.map(function(pet) {
return Number(pet.id);
});
console.log(pets);
var petIds = pets.map(function (pet) {
petId = parseInt(pet.id);
return petId;
});
I want to make use of Immutable's functions to update my structure from this structure but I'm uncertain in how to do it. My tags shouldn't be an array but should become objects just for posting to my REST api.
There are several examples on how to update deep properties and nested arrays, but I want to change values 2 arrays deep.
order: {
createDate: '2016-08-07',
pickupDate: '2017-02-02',
items: [
{
price: '25',
tags: [
'Blue',
'Pants'
]
}
]
}
to this structure
order: {
createDate: '2016-08-07',
pickupDate: '2017-02-02',
items: [
{
price: '25',
tags: [
{
text: 'Blue'
},
{
text: 'Pants'
}
]
}
]
}
Something like this:
const { fromJS, Map } = require("immutable")
const obj = fromJS({
order: {
createDate: '2016-08-07',
pickupDate: '2017-02-02',
items: [
{
price: '25',
tags: [
'Blue',
'Pants'
]
}
]
}
})
const items = obj
.getIn(['order', 'items'])
.map((item) => {
const newTags = item
.get('tags')
.map((tag) => ({ text: tag }));
return item.set('tags', newTags);
});
const newMap = obj.setIn(['order', 'items'], items);