Hello suppose I have the following array:
let array = [
{
id: "1",
name: "name",
categories: [
{
subid: "10",
name: "name",
},
{
subid: "11",
name: "name",
}
]
},
{
id: "2",
name: "name",
categories: [
{
subid: "20",
name: "name",
},
{
subid: "21",
name: "name",
}
]
}
]
My goal is to take the id of each of the objects and add it to the inner array categories. So it would look like this:
let array = [
{
id: "1",
name: "name",
categories: [
{
subid: "10",
name: "name",
id: "1"
},
{
subid: "11",
name: "name",
id: "1"
}
]
},
{
id: "2",
name: "name",
categories: [
{
subid: "20",
name: "name",
id: "2"
},
{
subid: "21",
name: "name",
id: "2"
}
]
}
]
Here is what I have so far:
array.map(x => (x.id)) // returns new array of ids
// add these into the categories
Can someone help me figure this out using map? If map cant be used I think for each will work as well
With map method and spread syntax inside object you could do this.
let array = [{"id":"1","name":"name","categories":[{"subid":"10","name":"name"},{"subid":"11","name":"name"}]},{"id":"2","name":"name","categories":[{"subid":"20","name":"name"},{"subid":"21","name":"name"}]}]
let result = array.map(({id, categories, ...rest}) => ({
...rest, id, categories: categories.map((o) => ({...o, id}))
}))
console.log(result)
You can use Array.forEach() to iterate over the array and then use Array.map() on categories array to add the id prop to all its objects:
let array = [ { id: "1", name: "name", categories: [ { subid: "10", name: "name", }, { subid: "11", name: "name", } ] }, { id: "2", name: "name", categories: [ { subid: "20", name: "name", }, { subid: "21", name: "name", } ] } ];
array.forEach((o)=>{
o.categories = o.categories.map(cat=>Object.assign({},cat,{id : o.id}));
});
console.log(array);
What about nested map?
let arr = [
{
id: "1",
name: "name",
categories: [
{
subid: "10",
name: "name",
},
{
subid: "11",
name: "name",
}
]
},
{
id: "2",
name: "name",
categories: [
{
subid: "20",
name: "name",
},
{
subid: "21",
name: "name",
}
]
}
]
arr.map(x=>{
x.categories.map(y => {
y.id = x.id
})
})
console.log(arr)
You need to map all arrays with copied properties to get a new independent data with a new property.
let array = [{ id: "1", name: "name", categories: [{ subid: "10", name: "name", }, { subid: "11", name: "name", }] }, { id: "2", name: "name", categories: [{ subid: "20", name: "name", }, { subid: "21", name: "name", }] }],
updated = array.map(o => Object.assign(
{},
o,
{ categories: o.categories.map(p => Object.assign({}, p, { id: o.id })) }
));
console.log(updated);
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Using each of Jquery should do the job.
$.each(array,function(index,item){item.categories.id = item.id;});
Thanks.
Related
Below is the data that I am receiving and I am trying to filter so that a new array contains only objects with the desired location.
However, I'm running into an issue where my function is returning [], an empty array.
data:
[
{ data: [[Object], [Object], [Object]], id: 1 },
{ data: [[Object]], id: 2 },
{ data: [[Object], [Object], [Object], [Object]], id: 3 }
];
data[1]:
{"data": [{"name": "Joe", "job": "N/A", "location": "Los Angeles"}], "id": 2}
This is my current function:
const locations = ["Los Angeles", "Chicago"];
...
const filteredData = data.filter((i) =>
i.data.filter((j) => locations.includes(j.location)),
);
return filteredData;
What is wrong and how can I fix this and get it filtering correctly?
In the callback you pass to the Array.filter(), you need to return a boolean value to filter the array. If you do not return anything, the filter returns an empty array.
But in your case, you are returning inner filtered array that returns at least an empty array and the outer filter behaves it as a true value. So the outer filter will return all of the items in the original array. (not an empty one as you stated)
Also you are returning filteredData in a place where it results in a syntax error.
const data = [
{"data": [{"name": "Joe", "job": "N/A", "location": "Los Angeles"}], "id": 2},
{"data": [{"name": "Jane", "job": "N/A", "location": "Charlotte"}], "id": 3},
]
const locations = ["Los Angeles", "Chicago"];
const filteredData = data.filter((i) =>
i.data.filter((j) => locations.includes(j.location)).length > 0,
);
console.log(filteredData);
Another Option is use some() to get your expected result. This way you don't need to loop through all item in data array comparing to filter()
const data = [
{ data: [{ name: "Joe", job: "N/A", location: "Los Angeles" }], id: 2 },
{ data: [{ name: "Jane", job: "N/A", location: "Charlotte" }], id: 3 },
{ data: [{ name: "Sam", job: "N/A", location: "SSS" }], id: 4 },
{
data: [
{ name: "John", job: "N/A", location: "AAA" },
{ name: "Doe", job: "N/A", location: "BBB" },
],
id: 5,
},
];
const locations = ["Los Angeles", "Chicago", "AAA"];
const existData = data.filter(el =>
el.data.some(item => locations.includes(item.location))
);
console.log(existData);
If you also want to filter the data array, you can do like below.
const data = [
{ data: [{ name: "Joe", job: "N/A", location: "Los Angeles" }], id: 2 },
{ data: [{ name: "Jane", job: "N/A", location: "Charlotte" }], id: 3 },
{ data: [{ name: "Sam", job: "N/A", location: "SSS" }], id: 4 },
{
data: [
{ name: "John", job: "N/A", location: "AAA" },
{ name: "Doe", job: "N/A", location: "BBB" },
],
id: 5,
},
];
const locations = ["Los Angeles", "Chicago", "AAA"];
const filteredData = data.reduce((acc, cur) => {
const filteredItem = cur.data.filter(item => locations.includes(item.location));
if (filteredItem.length) {
acc.push({ ...cur, data: filteredItem });
}
return acc;
}, []);
console.log(filteredData);
How to return name and id property value of all arrays? The idea is to make a single map of all these arrays and return the id and name?
Something like this
filters.[key].map((option, index) => (
<ItemFilter key={index}>{option}</ItemFilter>
))
I have this array object
filters: {
"services": [
{
"id": "1b975589-7111-46a4-b433-d0e3c0d7c08c",
"name": "Bank"
},
{
"id": "91d4637e-a17f-4b31-8675-c041fe06e2ad",
"name": "Income"
}
],
"accountTypes": [
{
"id": "1f34205b-2e5a-430e-982c-5673cbdb3a68",
"name": "Digital Account"
}
],
"channels": [
{
"id": "875f8350-073e-4a20-be20-38482a86892b",
"name": "Chat"
}
]
}
You can use flatMap or flat to achieve the desired result.
Object.values(obj.filters).flatMap(v => v)
or
Object.values(obj.filters).flat()
const obj = {
filters: {
services: [
{
id: "1b975589-7111-46a4-b433-d0e3c0d7c08c",
name: "Bank",
},
{
id: "91d4637e-a17f-4b31-8675-c041fe06e2ad",
name: "Income",
},
],
accountTypes: [
{
id: "1f34205b-2e5a-430e-982c-5673cbdb3a68",
name: "Digital Account",
},
],
channels: [
{
id: "875f8350-073e-4a20-be20-38482a86892b",
name: "Chat",
},
],
},
};
const result = Object.values(obj.filters).flatMap(v => v);
console.log(result);
If option is referring to name in your example code it could look something like this:
Object.values(
{
filters: {
services: [
{
id: "1b975589-7111-46a4-b433-d0e3c0d7c08c",
name: "Bank",
},
{
id: "91d4637e-a17f-4b31-8675-c041fe06e2ad",
name: "Income",
},
],
accountTypes: [
{
id: "1f34205b-2e5a-430e-982c-5673cbdb3a68",
name: "Digital Account",
},
],
channels: [
{
id: "875f8350-073e-4a20-be20-38482a86892b",
name: "Chat",
},
],
},
}.filters
)
.flat()
.map(({ name, index }) => <ItemFilter key={index}>{name}</ItemFilter>);
I have a following product object where it has variants and variants are dependent with attributes. For example, Product A has variants of
size M with color Black, Grey
Size L with color Black
To show it in object format this is how it looks
{
"variants": [{
"id": "1",
"name": "Variant name 1",
"price": null,
"stock": 2,
"variantAttributes": [{
"attribute": {
"id": "2",
"name": "Size"
},
"values": [{
"id": "1",
"name": "Medium",
"value": "M"
}]
},
{
"attribute": {
"id": "3",
"name": "Color"
},
"values": [{
"id": "3",
"name": "Black",
"value": "#000"
}]
}
]
},
{
"id": "2",
"name": "Variant name 2",
"price": null,
"stock": 2,
"variantAttributes": [{
"attribute": {
"id": "2",
"name": "Size"
},
"values": [{
"id": "2",
"name": "Large",
"value": "L"
}]
},
{
"attribute": {
"id": "3",
"name": "Color"
},
"values": [{
"id": "3",
"name": "Black",
"value": "#000"
}]
}
]
}
]
}
Now the problem is I could not find the variant id the user has selected. For e.g if user selects product of size 'M' and of color 'Black' then the variant id should be '1' as per the example I have shared in object.
This is the UI
To show the attributes this is how I have done
function productVariantAttributesPicker(productVariantsAttributes, setSizeGuideOpen, handleColorChange,handleSizeChange,rest) {
return Object.keys(productVariantsAttributes).map(
(productVariantsAttributeId,i) => {
const productVariantsAttribute =
productVariantsAttributes[productVariantsAttributeId];
const { slug, id } = productVariantsAttribute.attribute;
if (slug === "color") {
return <ColorPicker key={i} colorVariant={productVariantsAttributes[id]} handleColorChange={handleColorChange} selectedColor={rest.selectedColor}/>;
}
if (slug === "size") {
return (
<SizePicker
key={i}
sizeVariant={productVariantsAttributes[id]}
// setDisplaySizesOpen={rest.setDisplaySizesOpen}
setSizeGuideOpen={setSizeGuideOpen}
handleSizeChange={handleSizeChange}
selectedSize={rest.selectedSize}
/>
);
}
}
);
}
<div>
{productVariantAttributesPicker(
variants,
setSizeGuideOpen,
handleColorChange,
handleSizeChange,
{selectedSize,selectedColor}
)}
{selectedColor && selectedSize && (
<div>
<AddToCart handleAddToCart={handleAddToCart}></AddToCart>
</div>
)}
</div>
Can anyone help me to find variant id based on attributes selected by user where the selected atrributes is in such form?
const selected_size = {id: "1", name: "Medium", value: "M"}
const selected_color = {id: "3", name: "Black", value: "#000""}
If I understand correctly, you need to find a variant which its variantAttributes contains both selected_size and selected_color.
If so, the logic should is something like:
function hasAttr(variantAttribute, id, value) {
return variantAttribute.find(
variant => {
return variant.values.some((attrValue) => (attrValue.id === id && attrValue.value === value))
}
);
}
const variant = variants.find(
(variant) => {
return hasAttr(variant.variantAttributes, selected_size.id, selected_size.value) &&
hasAttr(variant.variantAttributes, selected_color.id, selected_color.value);
}
);
There is more generic way but I simplified the example to be more clear.
Demo
const variants = [{
id: '1',
name: 'Variant name 1',
price: null,
stock: 2,
variantAttributes: [{
attribute: {
id: '2',
name: 'Size',
},
values: [{
id: '1',
name: 'Medium',
value: 'M',
}, ],
},
{
attribute: {
id: '3',
name: 'Color',
},
values: [{
id: '3',
name: 'Black',
value: '#000',
}, ],
},
],
},
{
id: '2',
name: 'Variant name 2',
price: null,
stock: 2,
variantAttributes: [{
attribute: {
id: '2',
name: 'Size',
},
values: [{
id: '2',
name: 'Large',
value: 'L',
}, ],
},
{
attribute: {
id: '3',
name: 'Color',
},
values: [{
id: '3',
name: 'Black',
value: '#000',
}, ],
},
],
},
];
const selected_size = {
id: '1',
name: 'Medium',
value: 'M'
};
const selected_color = {
id: '3',
name: 'Black',
value: '#000'
};
function hasAttr(variantAttribute, id, value) {
return variantAttribute.find(
variant => {
return variant.values.some((attrValue) => (attrValue.id === id && attrValue.value === value))
}
);
}
const variant = variants.find(
(variant) => {
return hasAttr(variant.variantAttributes, selected_size.id, selected_size.value) &&
hasAttr(variant.variantAttributes, selected_color.id, selected_color.value);
}
);
console.log(variant);
I have these two arrays:
main:
[
{ id: "1"},
{ id: "2"},
{ id: "3"}
]
filtered:
[
{ id: "80", link_id: "1"},
{ id: "50", link_id: null},
{ id: "67", link_id: "3"}
]
I need to get the items of main which have as id those contained in filtered with the property: link_id, I tried with:
main.filter(x => filtered.includes(x.id));
the problem is that this will return null, and also this doesn't allow me to check if link_id is null
var main = [{
id: "1"
},
{
id: "2"
},
{
id: "3"
}
],
filtered = [{
id: "80",
link_id: "1"
},
{
id: "50",
link_id: null
},
{
id: "67",
link_id: "3"
}
],
result = main.filter(x =>
filtered.includes(x.id)
);
console.log(result)
Try with some() method
var main = [
{ id: "1"},
{ id: "2"},
{ id: "3"}
]
var filtered = [
{ id: "80", link_id: "1"},
{ id: "50", link_id: null},
{ id: "67", link_id: "3"}
]
console.log(main.filter(x => filtered.some(item => item.link_id === x.id) ));
you are close, basically you need to check in each item of the filtered array.
includes is more for a plain object as the documentation states.
check the snippet below, you can use findIndex, find or some to get if the element exist on the filtered array.
const main = [{
id: "1"
},
{
id: "2"
},
{
id: "3"
}
]
const filtered = [{
id: "80",
link_id: "1"
},
{
id: "50",
link_id: null
},
{
id: "67",
link_id: "3"
}
]
const resultFindIndex = main.filter(item => -1 !== filtered.findIndex(filteredItem => item.id === filteredItem.link_id))
const resultFind = main.filter(item => filtered.find(filteredItem => item.id === filteredItem.link_id))
const resultSome = main.filter(item => filtered.some(filteredItem => item.id === filteredItem.link_id))
console.log(resultFindIndex)
console.log(resultFind)
console.log(resultSome)
Given the following data set:
const users = {
"1": { id: "1", name: "Alex" },
"2": { id: "2", name: "John" },
"3": { id: "3", name: "Paul" }
};
const memberships = [
{ userId: "1", groupId: "1" },
{ userId: "2", groupId: "2" },
{ userId: "3", groupId: "1" }
];
What is an effective way to achieve following desired result?
const usersByGroupId = {
"1": [{ id: "1", name: "Alex" }, { id: "3", name: "Paul" }],
"2": [{ id: "2", name: "John" }]
}
I came up with the following (using Lodash):
const usersByGroupId = mapValues(
groupBy(memberships, "groupId"),
memberships => memberships.map(membership => users[membership.userId])
);
I'm not that familiar with big O notation, but I can imagine the performance of the above solution is pretty terrible on large sets. Any suggestions for improvement?
You don't really need lodash — you can do this in one step with reduce(). Just check if the key exists, if so push, if not set a new array and push. It just requires one iteration of the membership array and for each a lookup in the users object (which is more-or-less constant time) making this a linear time operation.
const users = {"1": { id: "1", name: "Alex" },"2": { id: "2", name: "John" },"3": { id: "3", name: "Paul" }};
const memberships = [{ userId: "1", groupId: "1" },{ userId: "2", groupId: "2" },{ userId: "3", groupId: "1" }];
let groups = memberships.reduce((obj, {userId, groupId}) => {
(obj[groupId] || (obj[groupId] = []) ).push(users[userId])
return obj
}, {})
console.log(groups)