Unable to flatten an array of objects into a single array - javascript

I am trying to flatten an array of objects. The only real informations i require is the arrays compacted into a single array.
The content is as follows:
const content = [
{ "chocolate" : [1] },
{ "banana" : [5] },
{ "soap" : [2] },
{ "tea" : [4] },
];
All i am interested in is the values in the array. So desired result would be:
const result = [1,5,2,4]
I have tried
Object.keys(content).map((val) => Object.values(content[val]));
and even tried creating a function
const flatten = ({ children = [], ...rest }) => [rest, ...children.flatMap(flatten)];
and calling it like so:
console.log(flatten(content));
but no luck.
Help?

The easiest way is to flat-map the entries, and pop the first value off of the object.
const
content = [
{ "chocolate" : [1] },
{ "banana" : [5] },
{ "soap" : [2] },
{ "tea" : [4] },
],
numbers = content.flatMap((obj) => Object.values(obj).pop());
console.log(JSON.stringify(numbers)); // [1, 5, 2, 4]

// source variable
const content = [{
"chocolate": [1]
}, {
"banana": [5]
}, {
"soap": [2]
}, {
"tea": [4]
}]
// to store result value
const result = [];
// lopoping though each object and accesing values of pbject using **Object.values(obj)** an array indexes.
content.forEach(val => result.push(Object.values(val)[0][0]));
// Printing result
console.log(result);

const result = content.map(o => Object.values(o).shift()[0])

You should use flatMap with Object.values:
const content = [{"chocolate": [1]}, {"banana": [5]},{"soap": [2]},{"tea": [4]}]
const res = content.flatMap(e => Object.values(e)[0]);
console.log(res);

As easy as this content.flatMap(obj => Object.values(obj)[0])

Related

Create an array of objects based on an object if one or more properties have multiple values differentiated by a comma

i'm trying to duplicate objects based on two properties that have multiple values differentiated by a comma.
For example:
I have an object
const obj = {
id: 1
date: "2021"
tst1: "111, 222"
tst2: "AAA, BBB"
}
And I would like the result to be an array of 2 objects in this case (because there are 2 values in tst1 OR tst2, these 2 properties will always have the same nr of values differentiated by a comma)
[{
id: 1,
date: "2021",
tst1: "111",
tst2: "AAA",
},
{
id: 1,
date: "2021",
tst1: "222",
tst2: "BBB",
}]
What I tried is this:
I created a temporary object
const tempObject = {
id: obj.id,
date: obj.date,
}
And then I would split and map the property that has multiple values, like this:
cont newObj = obj.tst1.split(",").map(function(value) {
let finalObj = {}
return finalObj = {
id: tempObject.id,
date: tempObject.date,
tst1: value,
})
And now, the newObj is an array of objects and each object contains a value of tst1.
The problem is I still have to do the same for the tst2...
And I was wondering if there is a simpler method to do this...
Thank you!
Here is an example that accepts an array of duplicate keys to differentiate. It first maps them to arrays of entries by splitting on ',' and then trimming the entries, then zips them by index to create sub-arrays of each specified property, finally it returns a result of the original object spread against an Object.fromEntries of the zipped properties.
const mapDuplicateProps = (obj, props) => {
const splitProps = props.map((p) =>
obj[p].split(',').map((s) => [p, s.trim()])
);
// [ [[ 'tst1', '111' ], [ 'tst1', '222' ]], [[ 'tst2', 'AAA' ], [ 'tst2', 'BBB' ]] ]
const dupeEntries = splitProps[0].map((_, i) => splitProps.map((p) => p[i]));
// [ [[ 'tst1', '111' ], [ 'tst2', 'AAA' ]], [[ 'tst1', '222' ], [ 'tst2', 'BBB' ]] ]
return dupeEntries.map((d) => ({ ...obj, ...Object.fromEntries(d) }));
};
const obj = {
id: 1,
date: '2021',
tst1: '111, 222',
tst2: 'AAA, BBB',
};
console.log(mapDuplicateProps(obj, ['tst1', 'tst2']));
Not sure if that's what you're searching for, but I tried making a more general use of what you try to do:
const duplicateProperties = obj => {
const properties = Object.entries(obj);
let acc = [{}];
properties.forEach(([key, value]) => {
if (typeof value === 'string' && value.includes(',')) {
const values = value.split(',');
values.forEach((v, i) => {
if (!acc[i]) {
acc[i] = {};
}
acc[i][key] = v.trim();
});
} else {
acc.forEach(o => o[key] = value);
}
});
return acc;
};
const obj = {
id: 1,
date: '2021',
tst1: '111, 222',
tst2: 'AAA, BBB',
};
console.log(duplicateProperties(obj));
You could start by determining the length of the result using Math.max(), String.split() etc.
Then you'd create an Array using Array.from(), returning the correct object for each value of the output index.
const obj = {
id: 1,
date: "2021",
tst1: "111, 222",
tst2: "AAA, BBB",
}
// Determine the length of our output array...
const length = Math.max(...Object.values(obj).map(s => (s + '').split(',').length))
// Map the object using the relevant index...
const result = Array.from({ length }, (_, idx) => {
return Object.fromEntries(Object.entries(obj).map(([key, value]) => {
const a = (value + '').split(/,\s*/);
return [key, a.length > 1 ? a[idx] : value ]
}))
})
console.log(result)
.as-console-wrapper { max-height: 100% !important; }

Filter Multidimensional Array with Another Array Values - JavaScript [duplicate]

I have two array, One of them is like this:
const array1 = [
Object {
"ItemId": 1,
},
Object {
"ItemId": 2,
},
]
other array is :
const array2 = [
Object {
"obj1": Object {
"Id": 4736,
},
"obj2": Object {
"ItemId": 1,
},
}
]
I want to get items in array1, which are not equals in obj2 of array2 .
I tried this but doesnt work
array1.filter(function (item) {
return array2.map((x) => {
return x.obj2 != item;
});
instead of array2.map, you're looking for Array.protype.some or Array.prototype.every. Why?
array1.filter is expecting a truthy value for every item.
array2.map is returning an array (!) with the results of its callback. In your case it's the result of each comparisson x.obj2 != item. It could look something like this: [true, false]. But this array will always evaluate to true.
array2.some() or array2.every() also iterate over the array but will return a boolean for the condition you're using. You can try for yourself and check the code sample afterwards.
const array1 = [
{
"ItemId": 1,
},
{
"ItemId": 2,
},
];
const array2 = [
{
"obj1": {
"ItemId": 4736,
},
"obj2": {
"ItemId": 1,
},
},
];
// errornous filter usage
const test = array1.filter(item => {
const arr = array2.map(x => x.obj2 !== item);
return arr;
});
// suggestion
const filteredResult = array1.filter(item => {
// both ways work
// return array2.every(x => x.obj2.ItemId !== item.ItemId);
return !array2.some(x => x.obj2.ItemId === item.ItemId);
});
console.log('initial result', test);
console.log('correct result', filteredResult);
Try this
array1=array1.filter((item) => {
return array2[0].obj2.ItemId !== item.ItemId;
})

Transform an array of objects by removing object properties not contained in another array

A long title, so I´ll explain the problem by example. I have an array of objects:
const myObjects = [
{
id: 1,
name: "a",
stuff: "x"
},
{
id: 2,
name: "b",
stuff: "y"
},
];
Then I have another array of objects like this:
const myTemplate=[
{
desiredProperty: "name",
someOtherProperty: "..."
},
{
desiredProperty: "stuff",
someOtherProperty: "..."
},
];
Now I want to transform myObjects array to new one, so that the individual objects contain only the properties listed in desiredProperty of each object in myTemplate.
The result should look like this:
myResult = [
{
name: "a",
stuff: "x"
},
{
name: "b",
stuff: "y"
}
]
How to achieve this?
This approach lets you partially apply the template to get back a reusable function to run against multiple sets of inputs:
const convert = (template, keys = new Set (template .map (t => t .desiredProperty))) => (xs) =>
xs .map (
(x) => Object .fromEntries (Object .entries (x) .filter (([k, v]) => keys .has (k)))
)
const myObjects = [{id: 1, name: "a", stuff: "x"}, {id: 2, name: "b", stuff: "y"}]
const myTemplate= [{desiredProperty: "name", someOtherProperty: "..."}, {desiredProperty: "stuff", someOtherProperty: "..."}]
console .log (
convert (myTemplate) (myObjects)
)
But I agree with the comment that the template here is better expressed as an array of keys to keep.
The following code creates a Set of the keys you want to keep. Then, we map over your myObjects array and only keep the object keys that are in the toKeep Set.
const myObjects=[{id:1,name:"a",stuff:"x"},{id:2,name:"b",stuff:"y"}];
const myTemplate=[{desiredProperty:"name",someOtherProperty:"..."},{desiredProperty:"stuff",someOtherProperty:"..."}];
const toKeep = new Set(myTemplate.map(t => t.desiredProperty));
const newObjs = myObjects.map(o => {
const obj = {};
for (let key in o) {
if (toKeep.has(key)) {
obj[key] = o[key];
}
}
return obj;
});
console.log(newObjs);

Destructuring array of objects in es6

In es6, how can i simplify the following lines using destructuring?:
const array0 = someArray[0].data;
const array1 = someArray[1].data;
const array2 = someArray[2].data;
Whether using destructuring would actually be a simplification is debatable but this is how it can be done:
const [
{ data: array0 },
{ data: array1 },
{ data: array2 }
] = someArray
Live Example:
const someArray = [
{ data: 1 },
{ data: 2 },
{ data: 3 }
];
const [
{ data: array0 },
{ data: array1 },
{ data: array2 }
] = someArray
console.log(array0, array1, array2);
What is happening is that you're first extracting each object from someArray then destructuring each object by extracting the data property and renaming it:
// these 2 destructuring steps
const [ obj1, obj2, obj3 ] = someArray // step 1
const { data: array0 } = obj1 // step 2
const { data: array1 } = obj2 // step 2
const { data: array2 } = obj3 // step 2
// written together give
const [
{ data: array0 },
{ data: array1 },
{ data: array2 }
] = someArray
Maybe combine destructuring with mapping for (potentially) more readable code:
const [array0, array1, array2] = someArray.map(item => item.data)
Live Example:
const someArray = [
{ data: 1 },
{ data: 2 },
{ data: 3 }
];
const [array0, array1, array2] = someArray.map(item => item.data)
console.log(array0, array1, array2);
I believe what you actually want is
const array = someArray.map(x => x.data)
If you really want three variables (Hint: you shouldn't), you can combine that mapping with destructuring:
const [array0, array1, array2] = someArray.map(x => x.data)
If you want to do with this pure JS then follow this code snippet. It will help you.
let myArray = [
{
"_id": "1",
"subdata": [
{
"subid": "11",
"name": "A"
},
{
"subid": "12",
"name": "B"
}
]
},
{
"_id": "2",
"subdata": [
{
"subid": "12",
"name": "B"
},
{
"subid": "33",
"name": "E"
}
]
}
]
const array = myArray.map(x => x.subdata).flat(1)
const isExist = (key,value, a) => {
return a.find(item => item[key] == value)
}
let a = array.reduce((acc, curr) => {
if(!isExist('subid', curr.subid, acc)) {
acc.push(curr)
}
return acc
}, [])
console.log(a)
const myInfo = someArray.map((item) => {
const {itemval1, itemval2} = item;
return(
//return data how you want it eg:
<p>{itemval1}</p>
<p>{itemval2}</p>)
})
This is how I did it in react, correct me if m wrong, I'm still new to this world
#Daniel, I presume you were looking to destructure a nested Object in an array of Objects. Following #nem035 was able to extract the nested Object's property using his pattern.
What is happening is that you're first extracting each object from addresses array then destructuring each object by extracting its properties and renaming it including the nested Object:
addresses = [
{
locality:"Sarjapura, Bangalore",
coordinates:{latitude:"12.901160", longitude:"77.711680"}
},
{
locality:"Vadakara, Kozhikode",
coordinates:{latitude:"11.588980", longitude:"75.596450"}
}
]
const [
{locality:loc1, coordinates:{latitude:lat1, longitude:ltd1}},
{locality:loc2, coordinates:{latitude:lat2, longitude:ltd2}}
] = addresses
console.log(`Latitude of Vadakara :: ${lat2}`)

combine javascript objects with inner array with same key (similar to foriegn key )

Obj1 = [
{
'id':1,
'name':'apple'
},
{
'id':2,
'name':'mango'
}
]
Obj2 = [
{
'parentId' : 1,
'time': [1,2,3]
},
{
'parentId' : 1,
'time': [4,5,6]
},
{
'parentId' : 1,
'time': [7,8,9]
},
{
'parentId' : 2,
'time': [11,12]
}
]
result = [
{
'id':1,
'name':'apple',
'time': [1,2,3,4,5,6,7,8,9]
},
{
'id':2,
'name':'mango',
'time': [11,12]
},
]
How to combine these two objects who have same key in common with
NodeJs or Javascript and get the following resulting object.
without using Jquery or any other framework.
Note : NodeJs application
You can use Array#map(), Array#filter() and concat()
Explication
arr1.map(a1=>{...}) => Create a new array based on arr1
arr2.filter(a2=>a2.prentId===a1.id) => Keep all the items with the parentId equals to the current id
.map(a2=>a2.time) => only keep the time array
let times is an array of array of times : [[1,2,3],[4,5,6]]
[].concat.apply([], times) => flatten the times nested array
const arr1=[{id:1,name:"apple"},{id:2,name:"mango"}],arr2=[{parentId:1,time:[1,2,3]},{parentId:1,time:[4,5,6]},{parentId:1,time:[7,8,9]},{parentId:2,time:[11,12]}];
let result = arr1.map(a1=>{
let times = arr2.filter(a2=>a2.parentId===a1.id).map(a2=>a2.time);
a1.time = [].concat.apply([], times);
return a1;
});
console.log(result);
const obj1=[{'id':1,'name':'apple'},{'id':2,'name':'mango'}];
const obj2=[{'parentId':1,'time':[1,2,3]},{'parentId':1,'time':[4,5,6]},{'parentId':1,'time':[7,8,9]},{'parentId':2,'time':[11,12]}];
const res = obj1.map(el => Object.assign(el, {time: obj2.filter(i => el.id === i.parentId).map(({time}) => time).join(',').split(',')}))
console.log(res)

Categories