Flatten inner array but assign outer properties - javascript

I have an input like this:
var input = [
{
"inner_array": [
{
"inner_data": "inner_data1"
},
{
"inner_data": "inner_data2"
}
],
"outer_data": "outer_data",
}
];
And I'd like to process it so it becomes this.
var output = [
{
"inner_data": "inner_data1",
"outer_data": "outer_data",
},
{
"inner_data": "inner_data2",
"outer_data": "outer_data",
}
];
In words: I'd like to flatten an inner array, while still keeping the outer array's properties. Does this have an easy solution (with built in lambda array functions), or should I write a function myself which handles this?

You could use .flatMap() on your input array to loop over each object, along with an inner .map() to map each inner_array to a new object. The new object can be a combination of the outer_data value along with the inner_data value. The .flatMap() method will then merge all returned objects from the inner .map() calls for each object within input into one resulting array:
const input = [{ "inner_array": [{ "inner_data": "inner_data1" }, { "inner_data": "inner_data2" } ], "outer_data": "outer_data", }];
const res = input.flatMap(obj => obj.inner_array.map(inner => ({
...inner,
outer_data: obj.outer_data
})));
console.log(res);

Related

Map function to build an array from filtered object

I'm trying to get my head around map functions currently without much success.
I currently have a list of objects and am trying to remap to a new object using the map function to return a map indexed by the created property with a list of wooids.
Having written my map function, I only seem to be returning the last time.
const variants = [
{
created: '2022-03-06',
hashname: 'c78ba80402290724609a5e98c369c90984494152',
hashobject: '80864e6329d5e305a512ace872ad7d56a3f41095',
hashparent: '19c5d50ddddeb7c9a92469df78c47d9d611f1599',
action: 'added',
wooid: 7288
},
{
created: '2022-03-06',
hashname: 'c78ba80402290724609a5e98c369c90984494152',
hashobject: '80864e6329d5e305a512ace872ad7d56a3f41095',
hashparent: '19c5d50ddddeb7c9a92469df78c47d9d611f1599',
action: 'added',
wooid: 7289
}
]
const res = Object.fromEntries(variants.map(k => [k.created, [k.wooid]]))
console.log(res)
Current output
{ '2022-03-06': [ 7289 ] }
Desired output:
{ '2022-03-06': [ 7289, 7288 ] }
Any help would be greatly appreciated as I'm unsure how to dynamically populate the array to include all other entires (6 in total).
Use Array.prototype.reduce() to build up your object. Check if you already have a key for each created value and if not, create an empty array. Then append the wooid value
const variants = [{"created":"2022-03-06","hashname":"c78ba80402290724609a5e98c369c90984494152","hashobject":"80864e6329d5e305a512ace872ad7d56a3f41095","hashparent":"19c5d50ddddeb7c9a92469df78c47d9d611f1599","action":"added","wooid":7288},{"created":"2022-03-06","hashname":"c78ba80402290724609a5e98c369c90984494152","hashobject":"80864e6329d5e305a512ace872ad7d56a3f41095","hashparent":"19c5d50ddddeb7c9a92469df78c47d9d611f1599","action":"added","wooid":7289}]
const res = variants.reduce((acc, { created, wooid }) => ({
...acc,
[ created ]: [
...acc[created] ?? [], // init to an empty array if unset
wooid
]
}), {})
console.log(res)
This will collect wooid values by created in the order they appear in the original data.

How to find dynamically a key values inside an object?

each API request I'm making contains different keys values inside a specific object.
How can I dynamically get the Number value of the second key? ("123112042")
"salesRanks": {
"281052": [ keepaTime, salesRank, ... ]
"123112042": [ keepaTime, salesRank, ... ]
}
Target the Object.keys and get the second index.
const data = {
salesRanks: {
"281052": [1, 1],
"123112042": [2, 2]
}
};
console.log(Object.keys(data.salesRanks)[1]);
Although an object's keys are not really meant to be ordered, you could write an object iterator and assign with destructuring like this:
const obj = {
salesRanks: {
281052: ["keepaTime", "salesRank"],
123112042: ["keepaTime", "salesRank"],
[Symbol.iterator]: function () {
return Object.keys(this).values();
}
},
};
const {
salesRanks: [, second],
} = obj;
console.log(second);

Javascript - how to loop through dict inside a list

So I am pretty new when it comes to Javascript and it is as simple as read a json list with a value of:
{
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
}
What I would like to do is to have both the URL and the amount of numbers etc
"https://testing.com/en/p/-12332423/" and "999"
and I would like to for loop so it runs each "site" one by one so the first loop should be
"https://testing.com/en/p/-12332423/" and "999"
second loop should be:
"https://testing.com/en/p/-123456/" and "123"
and so on depending on whats inside the json basically.
So my question is how am I able to loop it so I can use those values for each loop?
As Adam Orlov pointed out in the coment, Object.entries() can be very useful here.
const URLobj = {
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
};
URLobj.URL.forEach(ob => {
console.log('ob', ob);
const entries = Object.entries(ob)[0]; // 0 just means the first key-value pair, but because each object has only one we can just use the first one
const url = entries[0];
const number = entries[1];
console.log('url', url);
console.log('number', number);
})
You mean something like this using Object.entries
const data = {
"URL": [
{"https://testing.com/en/p/-12332423/": "999"},
{"https://testing.com/en/p/-123456/": "123"},
{"https://testing.com/en/p/-456436346/": "422"}
]
}
data.URL.forEach(obj => { // loop
const [url, num] = Object.entries(obj)[0]; // grab the key and value from each entry - note the [0]
console.log("Url",url,"Number", num); // do something with them
})
let's call your object o1 for simplicity. So you can really go to town with this link - https://zellwk.com/blog/looping-through-js-objects/
or you can just use this code :
for(var i = 0; i < o1.URL.length; i++) {
//each entry
var site = Object.keys(URL[i]) [0];
var value = Object.values(URL[i]) [0];
// ... do whatever
}
don't forget each member of the array is an object (key : value) in its own right
You can extract the keys and their values into another object array using map
Then use the for loop on the newly created array. You can use this method on any object to separate their keys and values into another object array.
const data = {
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
}
var extracted = data.URL.map(e => ({
url: Object.keys(e)[0],
number: Object.values(e)[0]
}))
extracted.forEach((e) => console.log(e))

javascript recursive function concat not working

I have a nested array of objects like below and I'm trying to push all the values in to a single array. all the values are located in sp->it->value or sp->it->it->value
[
{
"sp": [
{
"it":[
{"value":5}
]
},
...
],
"b": {
...
}
},
{
"sp": [
{
"it":[
{"nm":5}
]
}
],
"b": {
...
}
},
{
"sp": [
{
"it":[
{
"it":[
{"value":5}
]
}
]
}
],
"b": {
...
}
},
]
and here is what I have tried
const getValues = (js) => {
let values = []
js.map((val,i) => {
if("sp" in val) values.concat(getValues(val.sp))
else if("it" in val) values.concat(getValues(val.it))
else if("value" in val) values.push(val.value)
})
return values
}
I thought I could concatenate the returned value from the recursive call since it returns an array but the above code returns empty array. Any insights?
Edit fixed the typo on sp object. It is array of objects.
Array.prototype.concat()
The concat() method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.
So those lines do nothing:
if("sp" in val) values.concat(getValues(val.sp))
else if("it" in val) values.concat(getValues(val.it))
You need to write:
if("sp" in val) values = values.concat(getValues(val.sp))
else if("it" in val) values = values.concat(getValues(val.it))
And you should not use map if you don't use it's result. Use forEach instead.
This is because you are passing val.sp to function which is not array but it is an object and .map is a property of an array

React How to merge an array and an array of objects

I have this two states:
stateOne: [
'marca01',
'marca02'
]
stateTwo: [
{
PRODUCTO:'hat',
PRICE:1499,
CATEGORY:'Men'
},
{
PRODUCTO:'Shirt',
PRICE:1233,
CATEGORY:'Woman'
}
]
And I'm using lodash to merge both in a third state, but as you see the first state is an array and the second one is an array of objects so I can't merge these two like I want to...
Something like this:
stateThree: [
{
PRODUCTO:'hat',
PRICE:1499,
CATEGORY:'Men',
MARK:'marca01'
},
{
PRODUCTO:'Shirt',
PRICE:1233,
CATEGORY:'Woman',
MARK:'marca02'
}
]
How can I get the desired result (is not necessary to use lodash)
Without lodash :
const state3 = state2.map((product, index) => ({
...product,
MARK: state1[index]
}));
Here .map returns a new array whose new values are returned by the anonymous function.
The spread operator ...product flattens the previous object properties in the new object. This syntaxic sugar can be replaced by Object.assign.
Then we add a new MARK property based on the other state with the same index.
I used the map method and the spread operator in order to prevent state mutation which can be harmful in React.
You could iterate over the second array, and add the properties.
let s1 = [
'marca01',
'marca02'
]
let s2 = [
{
PRODUCTO:'hat',
PRICE:1499,
CATEGORY:'Men'
},
{
PRODUCTO:'Shirt',
PRICE:1233,
CATEGORY:'Woman'
}]
s2.forEach((x,i) => x.MARK = s1[i])
console.log(s2)
You can do like this:
stateThree = stateTwo.map( (element, i) => ({...element, MARK: stateOne[i] } ))

Categories