How to find the value by find() and map() - javascript

I would like to obtain the value of name using the code below.
When find(z => z.key.value === 123) be added to the code ,there will be this error :
x.obj.array_1.find(...).find is not a function
What's wrong with this code :
const data = [{
"obj": {
"array_1": [{
"array_2": [{
"array_3": [{
"key": {
"value": "123"
}
}]
}]
}]
},
"name": "obj1"
},
{
"obj": {
"array_1": [{
"array_2": [{
"array_3": [{
"key": {
"value": "456"
}
}]
}]
}]
},
"name": "obj2"
},
{
"obj": {
"array_1": [{
"array_2": [{
"array_3": [{
"key": {
"value": "789"
}
}]
}]
}]
},
"name": "obj3"
}
]
const name = data
.filter(x =>
x.obj.array_1.find(y => y.array_2).find(y => y.array_3).find(z => z.key.value === 123)
).map(x => x.name);
console.log(name)

Small fix here, this work provided that your real life data is also in this shape
After finding the propriate array_1 element that have array2[0] which has non-nil array_3, you have to access that array_3 to iterate and find the expected value
Edited (because array_2 and array_3 may have multiple elements): you have to extract all array_3 element (using flatMap to flatten the nested array) and do the condition check from that extracted array
const name = data
.filter((x) => {
const flattened_array_3 = x.obj.array_1.flatMap((array_1_el) =>
array_1_el.array_2.flatMap((array_2_el) => array_2_el.array_3)
)
return flattened_array_3.find((array_3_el) => +array_3_el.key.value === 123)
})
.map((x) => x.name)
Full code
const data = [
{
obj: {
array_1: [
{
array_2: [
{
array_3: [
{
key: {
value: "123",
},
},
],
},
],
},
],
},
name: "obj1",
},
{
obj: {
array_1: [
{
array_2: [
{
array_3: [
{
key: {
value: "456",
},
},
],
},
],
},
],
},
name: "obj2",
},
{
obj: {
array_1: [
{
array_2: [
{
array_3: [
{
key: {
value: "789",
},
},
],
},
],
},
],
},
name: "obj3",
},
]
const name = data
.filter((x) => {
const flattened_array_3 = x.obj.array_1.flatMap((array_1_el) =>
array_1_el.array_2.flatMap((array_2_el) => array_2_el.array_3)
)
return flattened_array_3.find((array_3_el) => +array_3_el.key.value === 123)
})
.map((x) => x.name)
console.log(name)
Reference: flatMap

x.obj.array_1.find(y => y.array_2)
is undefined.
Try to split your code

In order to work on this structure, I advise you to change the way you represent data.
It seems like some kind of output of tokenization. There have to bee tools to extract information from the path for example XPath, etc.
On the other hand below code should work for your case
The key point is using flatMap to rest inner arrays to upper one
const data = [{
"obj": {
"array_1": [{
"array_2": [{
"array_3": [{
"key": {
"value": "123"
}
}]
}]
}]
},
"name": "obj1"
},
{
"obj": {
"array_1": [{
"array_2": [{
"array_3": [{
"key": {
"value": "456"
}
}]
}]
}]
},
"name": "obj2"
},
{
"obj": {
"array_1": [{
"array_2": [{
"array_3": [{
"key": {
"value": "789"
}
}]
}]
}]
},
"name": "obj3"
}
]
var obj = data.find(x=> x.obj.array_1.flatMap(x=>x.array_2).flatMap(x=>x.array_3)[0].key.value==789)
console.log(obj.name)

Related

get size of value in a map javascript

I have below array object of key of Id and List of value pair. I want to get for each key what is the length of the value like
[
{
"key": "a5a5E0000003uzTQAQ",
"value": 1
},
{
"key": "a5a5E0000003uzYQAQ",
"value": 2
}
]
I am trying below code , but it is giving me undefined in the length of the value.
var message = [
{
"key": "a5a5E0000003uzTQAQ",
"value": [
{
"Name": "Features1"
}
]
},
{
"key": "a5a5E0000003uzYQAQ",
"value": [
{
"Name": "AEO Analysis - Engagement"
},
{
"Name": "AEO Analysis - Engagement 1",
}
]
}
]
let noOfFields = []
for (let key in message) {
if (message.hasOwnProperty(key)) {
noOfFields.push({key: key, value: message[key].length });
}
}
console.log(noOfFields)
You can use array.map
const message = [
{
"key": "a5a5E0000003uzTQAQ",
"value": [
{
"Name": "Features1"
}
]
},
{
"key": "a5a5E0000003uzYQAQ",
"value": [
{
"Name": "AEO Analysis - Engagement"
},
{
"Name": "AEO Analysis - Engagement 1",
}
]
}
]
const noOfFields = message.map((obj) => {
return {
key: obj.key,
value: obj.value.length
}
})
console.log(noOfFields)
Result:
[
{ key: 'a5a5E0000003uzTQAQ', value: 1 },
{ key: 'a5a5E0000003uzYQAQ', value: 2 }
]
If you want the length you just need this:
var message = [
{
"key": "a5a5E0000003uzTQAQ",
"value": [
{
"Name": "Features1"
}
]
},
{
"key": "a5a5E0000003uzYQAQ",
"value": [
{
"Name": "AEO Analysis - Engagement"
},
{
"Name": "AEO Analysis - Engagement 1",
}
]
}
]
let noOfFields = []
for (let key in message) {
if (message.hasOwnProperty(key)) {
noOfFields.push({key: key, value: message[key].value.length });
}
}
console.log(noOfFields)
It's a little misleading to call the length of the value 'value' though.

Filtering nested JSON array in javascript and returning inner array which matches a criteria

I have a json object like this:
{
"products": [
{
"ID": "001",
"Attributes": [
{
"value": "BESTSELLERS",
"identifier": "BEST_SELLER"
},
{
"value": "Color",
"identifier": "Green"
},
{
"value": "Size",
"identifier": "L"
}
],
"SKUs": [
{
"ID": "001_1",
"Attributes": [
{
"value": "BESTSELLERS",
"identifier": "BEST_SELLER"
},
{
"value": "Color",
"identifier": "Green"
},
{
"value": "Size",
"identifier": "L"
}
]
},
{
"ID": "001_2",
"Attributes": [
{
"value": "BESTSELLERS",
"identifier": "BEST_SELLER"
},
{
"value": "Color",
"identifier": "Yellow"
},
{
"value": "Size",
"identifier": "M"
}
]
}
]
},
{
"ID": "002",
"Attributes": [
{
"value": "BESTSELLERS",
"identifier": "BEST_SELLER"
},
{
"value": "Size",
"identifier": "L"
}
],
"SKUs": [
{
"ID": "002_1",
"Attributes": [
{
"value": "BESTSELLERS",
"identifier": "BEST_SELLER"
},
{
"value": "Color",
"identifier": "Black"
},
{
"value": "Size",
"identifier": "L"
}
]
},
{
"ID": "002_2",
"Attributes": [
{
"value": "BESTSELLERS",
"identifier": "BEST_SELLER"
},
{
"value": "Color",
"identifier": "Grey"
}
]
}
]
},
{
"ID": "003",
"Attributes": [
{
"value": "BESTSELLERS",
"identifier": "BEST_SELLER"
},
{
"value": "Color",
"identifier": "Blue"
}
],
"SKUs": []
}
]
}')
As you can see, products is an array which contains another array SKUs which contains another array Attributes.
I want to get all those SKUs which have BOTH the attributes - Size and Color for them.
So, it should return
SKUs 001_1, 001_2 and 002_1
So, i wrote the following code:
var obj = JSON.parse('<MyAboveJSONObjectHere>');
obj.products.filter( p => p.SKUs.filter(sku => sku.Attributes.filter(att =>
att.identifier === 'Color' && att.identifier === 'Size')))
But this is returning all 3 product objects inside the JSON.
Can you please tell what is wrong with my code expression ?
With reduce":
data.products.reduce((p, c) => (
(c.SKUs = c.SKUs.filter(
sku =>
sku.Attributes.some(att => att.value === "Color") &&
sku.Attributes.some(att => att.value === "Size")
)).length && p.push(c), p ),[]
);
data = {
products: [
{
ID: "001",
Attributes: [
{
value: "BESTSELLERS",
identifier: "BEST_SELLER"
},
{
value: "Color",
identifier: "Green"
},
{
value: "Size",
identifier: "L"
}
],
SKUs: [
{
ID: "001_1",
Attributes: [
{
value: "BESTSELLERS",
identifier: "BEST_SELLER"
},
{
value: "Color",
identifier: "Green"
},
{
value: "Size",
identifier: "L"
}
]
},
{
ID: "001_2",
Attributes: [
{
value: "BESTSELLERS",
identifier: "BEST_SELLER"
},
{
value: "Color",
identifier: "Yellow"
},
{
value: "Size",
identifier: "M"
}
]
}
]
},
{
ID: "002",
Attributes: [
{
value: "BESTSELLERS",
identifier: "BEST_SELLER"
},
{
value: "Size",
identifier: "L"
}
],
SKUs: [
{
ID: "002_1",
Attributes: [
{
value: "BESTSELLERS",
identifier: "BEST_SELLER"
},
{
value: "Color",
identifier: "Black"
},
{
value: "Size",
identifier: "L"
}
]
},
{
ID: "002_2",
Attributes: [
{
value: "BESTSELLERS",
identifier: "BEST_SELLER"
},
{
value: "Color",
identifier: "Grey"
}
]
}
]
},
{
ID: "003",
Attributes: [
{
value: "BESTSELLERS",
identifier: "BEST_SELLER"
},
{
value: "Color",
identifier: "Blue"
}
],
SKUs: []
}
]
};
console.log(data.products.reduce((p, c) => (
(c.SKUs = c.SKUs.filter(
sku =>
sku.Attributes.some(att => att.value === "Color") &&
sku.Attributes.some(att => att.value === "Size")
)).length && p.push(c), p ),[]
));
If I understand correctly you're wanting to obtain a list of SKU ID values from the supplied products array where those SKU items has Attribute sub-arrays which contained values of "Color" and "Size".
This can be achieved via a reduce(), where the reduction callback filters SKU items based on the Attributes criteria. Any filtered SKU items are then mapped to their ID field, and collected (via concat()) into the resulting output array as shown below:
const obj={"products":[{"ID":"001","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Green"},{"value":"Size","identifier":"L"}],"SKUs":[{"ID":"001_1","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Green"},{"value":"Size","identifier":"L"}]},{"ID":"001_2","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Yellow"},{"value":"Size","identifier":"M"}]}]},{"ID":"002","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Size","identifier":"L"}],"SKUs":[{"ID":"002_1","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Black"},{"value":"Size","identifier":"L"}]},{"ID":"002_2","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Grey"}]}]},{"ID":"003","Attributes":[{"value":"BESTSELLERS","identifier":"BEST_SELLER"},{"value":"Color","identifier":"Blue"}],"SKUs":[]}]};
/* Filter each product by the required SKU/attribute criteria */
const result = obj.products.reduce((output, product) => {
/* Determine if this products SKUs have contain requied attribute values */
return output.concat(product.SKUs.filter((sku) => {
const attributes = sku.Attributes;
/* Search the attributes of this sku, looking for any with values that
are color or size */
const hasColor = attributes.some((attribute) => attribute.value === 'Color');
const hasSize = attributes.some((attribute) => attribute.value === 'Size');
/* If both attribute values found then this sku matches required criteria */
return hasColor && hasSize;
})
/* Map any filtered sku to it's ID and concat the result to output */
.map(sku => sku.ID));
}, []);
console.log(result);
obj.products.map( p => {
return p.SKUs.map(sku => {
return sku.Attributes.filter(att => att.identifier === 'Color' && att.identifier === 'Size')}}
Try this, basically you need to first map through the arrays and only on the last one filter
I believe that you have to check value instead of identifier. Based on your object the value you are checking for is in the value key of the attribute object. You should also be checking for the array length of the return value of the inner filters. An empty array if passed in a condition will still be considered true that's why your filter always returns all the contents of your object. so the filter should look something like this.
obj.products.filter( p => p.SKUs.filter( att => att.Attributes.filter(inner => inner.value == 'Color' || inner.value == 'Size').length > 0 ? true : false).length > 0 ? true : false)

push elements of each object inside each object inside another array

I have two arrays, one is my original one called data which consists of :
const datas = [
{
name: 'core Test',
item: [
{
name: 'test/core/core.js',
item: "item1"
}
]
},
{
name: 'users Test',
item: [
{
name: 'test/users/user.js',
item: "item2"
}
]
}
]
And i have another array called replace, which i'm trying to push each of its elements inside my original one, inside the
const replace = [
{
type: "test1",
number: "1",
},
{
type: "test2",
number: "2",
}
]
Here is my code :
const transformedData = datas.map(data => {
data.item = data.item.map(x => ({
name: x.name,
type: replace.map(y=>{return y;})
}))
return data
})
The output i get :
[
{
"name": "core Test",
"item": [
{
"name": "test/core/core.js",
"type": [
{ "type": "test1", "number": "1" },
{ "type": "test2", "number": "2" }
]
}
]
},
{
"name": "users Test",
"item": [
{
"name": "test/users/user.js",
"type": [
{ "type": "test1", "number": "1" },
{ "type": "test2", "number": "2" }
]
}
]
}
]
The output i want :
[
{
"name": "core Test",
"item": [
{
"name": "test/core/core.js",
"type": { "type": "test1", "number": "1" }
}
]
},
{
"name": "users Test",
"item": [
{
"name": "test/users/user.js",
"type": { "type": "test2", "number": "2" }
}
]
}
]
This is because you're mapping all the way through the replace array every single time for each time you're inside of a value inside of datas. Instead you want to keep track of the index with your original map so then you only have one instance each time.
Try something like:
const transformedData = datas.map((data, index) => {
data.item = data.item.map(x => ({
name: x.name,
type: replace[index]
}))
return data;
});

replace value of each object inside array

I want to change the value of each objects inside the array. I want to do a path.parse(name).name on the name object inside of the item array and return this array with the new values
My array is like this :
[
{
"name": "core Test",
"item": [
{
"name": "test/core/core.js",
"item": []
}
]
},
{
"name": "users Test",
"item": [
{
"name": "test/users/user.js",
"item": []
}
]
}
]
here is my code :
array.forEach((element) => {
const { item } = element;
item.forEach((i) => {
const { name } = i;
const newname = path.parse(name).name;
console.log(newname);
});
});
The output i want is :
[
{
"name": "core Test",
"item": [
{
"name": "core",
"item": []
}
]
},
{
"name": "users Test",
"item": [
{
"name": "user",
"item": []
}
]
}
]
This will give you your desired output
const path = require('path')
const datas = [
{
name: 'core Test',
item: [
{
name: 'test/core/core.js',
item: []
}
]
},
{
name: 'users Test',
item: [
{
name: 'test/users/user.js',
item: []
}
]
}
]
const transformedData = datas.map(data => {
data.item = data.item.map(x => ({
name: path.parse(x.name).name,
item: x.item
}))
return data
})
console.log(transformedData )

filter an array of nested objects in 5 level

I am trying filter this array with .filter.
var objList = [
{
"name": "Object0Name",
"id": "Object0ID",
"Object1List": [
{
"id": "Object1id_A1",
"name": "Object1Name_A1",
"Object2List": [
{
"id": 187,
"name": "Object2Name_A1",
"Object3List": [
{
"id": "mammal",
"name": "mammal",
"Object4List": [
{
"id_client": "rabbit",
"Currency": "EUR"
},
{
"id_client": "cat",
"Currency": "EUR",
},
{
"id_client": "tiger",
"Currency": "EUR",
}
]
}
]
}
]
},
{
"id": "Object1id_B1",
"name": "Object1Name_B1",
"Object2List": [
{
"id": 189,
"name": "Object2Name_B1",
"Object3List": [
{
"id": "fish",
"name": "fish",
"Object4List": [
{
"id_client": "tiger shark",
"Currency": "EUR",
},
{
"id_client": "tuna",
"currency": "GBP",
},
]
}
]
}
]
}
]
}
]
var response= objList.filter(function(Object0List){
return Object0List.Object1List.filter(function(Object1List){
return Object1List.Object2List.filter(function(Object2List){
return Object2List.Object3List.filter(function(Object3List){
return Object3List.Object4List.filter(function(Object4List){
return Object4List.id_client==="tiger shark";
});
});
});
});
});
var myJSON = JSON.stringify(response);
console.log('The animal is:');
console.log(myJSON);
But the filter doesn't work. I am receiving all objects. I must receive:
[
{
"name": "Object0Name",
"id": "Object0ID",
"Object1List": [
{
"id": "Object1id_B1",
"name": "Object1Name_B1",
"Object2List": [
{
"id": 189,
"name": "Object2Name_B1",
"Object3List": [
{
"id": "fish",
"name": "fish",
"Object4List": [
{
"id_client": "tiger shark",
"Currency": "EUR",
}
]
}
]
}
]
}
]
}
]
Could someone help me find out what I'm doing wrong? I'm sure the problem is that I'm using the .filter function badly but it took several hours and I'm not capable of fixing it. I think that I do not understand this function for nested objects, I tried to filter the array of nested objects with lambda expressions but I'm also not able.
Thanks you very much.
You could check each property which is an array and take only filtered values.
This approach mutates the original array.
function filter(array, value) {
var temp = array.filter(o =>
Object.keys(o).some(k => {
var t = filter(Array.isArray(o[k]) ? o[k] : [], value);
if (o[k] === value) {
return true;
}
if (t && Array.isArray(t) && t.length) {
o[k] = t;
return true;
}
})
);
if (temp.length) {
return temp;
}
}
var array = [{ name: "Object0Name", id: "Object0ID", Object1List: [{ id: "Object1id_A1", name: "Object1Name_A1", Object2List: [{ id: 187, name: "Object2Name_A1", Object3List: [{ id: "mammal", name: "mammal", Object4List: [{ id: "rabbit", Currency: "EUR" }, { id: "cat", Currency: "EUR" }, { id: "tiger", Currency: "EUR" }] }] }] }, { id: "Object1id_B1", name: "Object1Name_B1", Object2List: [{ id: 189, name: "Object2Name_B1", Object3List: [{ id: "fish", name: "fish", Object4List: [{ id: "tiger shark", Currency: "EUR" }, { id: "tuna", currency: "GBP" }] }] }] }] }],
result = filter(array, 'tiger shark');
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I assume that every of your objects has this structure:
{
id: "sth",
name: "whatever"
children: [ /***/ ]
}
So then it is quite easy to filter recursively:
function filter(arr, search){
const result = [];
for(const {name, id, children} of arr){
children = filter(children, search);
if(children.length || id === search)
result.push({id, name, children });
}
return result;
}
Usable as:
var response = filter(objList, "tiger shark");

Categories

Resources