How to .map correctly this array of objects? - javascript

I'm not sure what I'm doing wrong but I would like to map an array of objects. This array of objects it's dynamic, this means sometimes it has 4 objects and sometimes 20, so I need to make sure it will work no matters how many entries it has:
var obj = [
{
"key": "one",
"value": "something"
},
{
"key": "two",
"value": "random"
},
{
"key": "blue",
"value": "chicken"
},
{
"key": "orange",
"value": "sportsman"
}
];
I need to pass this objects into one to send it through a POST call that should match this format:
form: {
'one': 'something',
'two': 'random',
'blue': 'chicken',
'orange': 'sportsman'
}
I can access to item.value but IDK why I can't item.key:
var obj = [
{
"key": "one",
"value": "something"
},
{
"key": "two",
"value": "random"
},
{
"key": "blue",
"value": "chicken"
},
{
"key": "orange",
"value": "sportsman"
}
];
var combined = obj.map(function combined(item) {
return {
item.key: item.value
};
})
console.log(combined);
Any ideas? Thanks.

You shouldn't return an object from your callback function. Return an array of the key and value, then use Object.fromEntries() to turn this into a single object with those keys and values.
var obj = [{
"key": "one",
"value": "something"
},
{
"key": "two",
"value": "random"
},
{
"key": "blue",
"value": "chicken"
},
{
"key": "orange",
"value": "sportsman"
}
];
var combined = Object.fromEntries(obj.map(item => [item.key, item.value]));
console.log(combined);

1) You can't use a map here because the map will return a new array. You can achieve this result using reduce
var obj = [
{
key: "one",
value: "something",
},
{
key: "two",
value: "random",
},
{
key: "blue",
value: "chicken",
},
{
key: "orange",
value: "sportsman",
},
];
const result = obj.reduce((acc, curr) => {
const { key, value } = curr;
acc[key] = value;
return acc;
}, {});
console.log(result);
2) You can also do this using for..of loop
var obj = [{
key: "one",
value: "something",
},
{
key: "two",
value: "random",
},
{
key: "blue",
value: "chicken",
},
{
key: "orange",
value: "sportsman",
},
];
const result = {};
for (let o of obj) {
result[o.key] = o.value;
}
console.log(result);

Related

find if an array is inside another nested array

I 'm trying to find if array1 is is inside the nested array2.data.
const array1 = [
{
name: "Color",
value: "Yellow",
},
{
name: "Size",
value: "Small",
},
];
const array2 = [
{
"id": 1,
"data": [
{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Small"
}
]
},
{
"id": 2,
"data": [
{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Medium"
}
]
},
{
"id": 3,
"data": [
{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Large"
}
]
},]
this is what I have tread but not giving me the result I need :
array2.map(( a ) => {
a.data.map(( data ) => {
array1.map((option) => {
if( data === option) {
return data;
}
});
});
});
JSON.stringify() the needle array (array1) and the data attribute of each array member in array2 and compare the two; if they match, array1 is present in array2:
const array1 = [{
name: "Color",
value: "Yellow",
},
{
name: "Size",
value: "Small",
},
];
const array2 = [{
"id": 1,
"data": [{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Small"
}
]
},
{
"id": 2,
"data": [{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Medium"
}
]
},
{
"id": 3,
"data": [{
"name": "Color",
"value": "Yellow"
},
{
"name": "Size",
"value": "Large"
}
]
},
];
const dataArrayIsPresentInArray2 = needle => !!array2.find(cv => JSON.stringify(cv.data) === JSON.stringify(needle));
console.log(dataArrayIsPresentInArray2(array1)); // true
As mentioned in the comments, this method will only work for data structures serializable with JSON.stringify().
If the order of the objects in array1 does not matter, you can iterate through every item and use Array.every to check whether each item in the data property after stringification is equal to an item in array1 after stringification.
const array1=[{name:"Color",value:"Yellow"},{name:"Size",value:"Small"}],array2=[{id:1,data:[{name:"Color",value:"Yellow"},{name:"Size",value:"Small"}]},{id:2,data:[{name:"Color",value:"Yellow"},{name:"Size",value:"Medium"}]},{id:3,data:[{name:"Color",value:"Yellow"},{name:"Size",value:"Large"}]}];
const contains = array2.some(e => e.data.every(f => array1.some(g => JSON.stringify(g) == JSON.stringify(f))));
console.log(contains)
if you wanna just to check if arr1 in arr2.date
i would probably just
loop over arr2.data and compare each iteration to arr1 and if it is the same return or change some value to know the output .
something like :
// var that represent if arr1 inside arr2.data
let arr1InsideArr2= false
for (let i of array2){
if (i.data == array1){
return arr1InsideArr2= true
}
}
and then do with the var arr1InsideArr2 whatever you want to check .

Issue adding key value pair to javascript object from an array

I have an object like this
let obj = {
"apple": {
"color": "red",
},
"banana": {
"color": "yellow"
}
}
I am getting an array of objects of this form
let arr = [
{
"count": "9904",
"fruit": "apple",
"type": "typea"
},
{
"count": "7142",
"fruit": "banana",
"type": "typeb"
},
{
"count": "4121",
"fruit": "apple",
"type": "typec"
}
]
I want to combine these two so that each item in objcan have variable no of properties so that final output look something like this
{
"apple": {
"color": "red",
"typea": "9904",
"typec": "4121"
},
"banana": {
"color": "yellow",
"typeb": "7142"
}
}
I tried running the array through a for loop but when I try to use the dynamic values in keys it shows error
for (let item of arr){
obj[item.fruit] = {...obj[item.fruit], item.type: item.count}
}
If instead of item.type I put some static value like "count" it works but I can't figure out how to use dynamic value
Can anyone suggest me what is the best way to accomplish this?
You should use computed property names with square brackets.
let obj = {
"apple": {
"color": "red",
},
"banana": {
"color": "yellow"
}
}
let arr = [
{
"count": "9904",
"fruit": "apple",
"type": "typea"
},
{
"count": "7142",
"fruit": "banana",
"type": "typeb"
},
{
"count": "4121",
"fruit": "apple",
"type": "typec"
}
]
for (let item of arr){
obj[item.fruit] = {...obj[item.fruit], [item.type]: item.count}
}
console.log(obj);
Here's a verbose and explicit example of how you can do this using Array.prototype.reduce.
(Note that MDN will be down for maintenance for up to an hour at some point today.)
const
obj = { apple:{color:"red"}, banana:{color:"yellow"} },
arr = [
{ fruit: "apple", type: "typeA", count: 9 },
{ fruit: "banana", type: "typeB", count: 7 },
{ fruit: "apple", type: "typeC", count: 4 }
];
arr.reduce( (theObj, current) => {
// Reduce loops through the array, updating theObj for each item
const
fruitName = current.fruit, // Gets fruit name
fruitObjInObj = theObj[fruitName], // Gets fruit obj
type = current.type, // Gets type from current item
count = current.count; // Gets count from current item
fruitObjInObj[type] = count; // Adds property to fruit obj
return theObj; // Gives theObj back to `reduce` for next loop
}, obj); // Tells `reduce` to use obj as theObj on first loop
console.log(obj);

Javascript merge array of objects based on incrementing key

This is what I have: I want to merge object which key begins with "path-"+i . And to strip "path-i" from keys in end result.
var arr = [
{
"key": "path-0-mp4",
"value": [
"media/video/01.mp4",
"media/video/01_hd.mp4"
]
},
{
"key": "path-0-quality",
"value": [
"720p",
"1080p"
]
},
{
"key": "path-1-mp4",
"value": [
"media/video/02.mp4",
"media/video/02_hd.mp4"
]
},
{
"key": "path-1-quality",
"value": [
"SD",
"HD"
]
}
]
This is a desired result:
var arr = [
[
{
"mp4": "media/video/01.mp4",
"quality": "720p"
},
{
"mp4": "media/video/01_hd.mp4",
"quality": "1080p"
},
],
[
{
"mp4": "media/video/02.mp4",
"quality": "SD"
},
{
"mp4": "media/video/02_hd.mp4",
"quality": "HD"
},
],
]
I started doing something but its not even close:
var key, new_key, value,j=0, z=0, parr = [], obj;
for(var i = 0;i<a.length;i++){
console.log('item:' ,a[i])
key = a[i].key, value = a[i].value
if(key.indexOf('path-'+j.toString()) > -1){
new_key = key.substr(key.lastIndexOf('-')+1)
console.log(key, new_key, value)
for(var z = 0;z<value.length;z++){
parr.push({[new_key]: value[z] })
}
}
}
console.log(parr)
[
{
"mp4": "media/video/01.mp4"
},
{
"mp4": "media/video/01_hd.mp4"
},
{
"quality": "720p"
},
{
"quality": "1080p"
}
]
edit:
Array could petencially hols different keys that would need grouping in the same way, for example:
var arr = [
{
"key": "path-0-mp4",
"value": [
"media/video/01.mp4",
"media/video/01_hd.mp4"
]
},
{
"key": "path-0-quality",
"value": [
"720p",
"1080p"
]
},
{
"key": "path-1-mp4",
"value": [
"media/video/02.mp4",
"media/video/02_hd.mp4"
]
},
{
"key": "path-1-quality",
"value": [
"SD",
"HD"
]
},
{
"key": "subtitle-0-label",
"value": [
"English",
"German",
"Spanish"
]
},
{
"key": "subtitle-0-src",
"value": [
"data/subtitles/sintel-en.vtt",
"data/subtitles/sintel-de.vtt",
"data/subtitles/sintel-es.vtt"
]
},
{
"key": "subtitle-1-label",
"value": [
"German",
"Spanish"
]
},
{
"key": "subtitle-1-src",
"value": [
"data/subtitles/tumblr-de.vtt",
"data/subtitles/tumblr-es.vtt"
]
}
]
This is a desired result (create new array for each different key):
var arr = [
[
{
"mp4": "media/video/01.mp4",
"quality": "720p"
},
{
"mp4": "media/video/01_hd.mp4",
"quality": "1080p"
},
],
[
{
"mp4": "media/video/02.mp4",
"quality": "SD"
},
{
"mp4": "media/video/02_hd.mp4",
"quality": "HD"
},
],
],
arr2 = [
[
{
"label": "English",
"src": "data/subtitles/sintel-en.vtt",
},
{
"label": "German",
"src": "data/subtitles/sintel-de.vtt"
},
{
"label": "Spanish",
"src": "data/subtitles/sintel-es.vtt"
}
],
[
{
"label": "Spanish",
"src": "data/subtitles/tumblr-es.vtt",
},
{
"label": "German",
"src": "data/subtitles/tumblr-de.vtt"
}
]
]
You could split the key property, omit the first path and take the rest as index and key. Then create a new array, if not exists and assign the values.
var data = [{ key: "path-0-mp4", value: ["media/video/01.mp4", "media/video/01_hd.mp4"] }, { key: "path-0-quality", value: ["720p", "1080p"] }, { key: "path-1-mp4", value: ["media/video/02.mp4", "media/video/02_hd.mp4"] }, { key: "path-1-quality", value: ["SD", "HD"] }],
result = data.reduce((r, { key, value }) => {
let [, i, k] = key.split('-');
r[i] = r[i] || [];
value.forEach((v, j) => (r[i][j] = r[i][j] || {})[k] = v);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you like to group by the first part of key, you could take an object with this group as key and assign the rest as above.
var data = [{ key: "path-0-mp4", value: ["media/video/01.mp4", "media/video/01_hd.mp4"] }, { key: "path-0-quality", value: ["720p", "1080p"] }, { key: "path-1-mp4", value: ["media/video/02.mp4", "media/video/02_hd.mp4"] }, { key: "path-1-quality", value: ["SD", "HD"] }, { key: "subtitle-0-label", value: ["English", "German", "Spanish"] }, { key: "subtitle-0-src", value: ["data/subtitles/sintel-en.vtt", "data/subtitles/sintel-de.vtt", "data/subtitles/sintel-es.vtt"] }, { key: "subtitle-1-label", value: ["German", "Spanish"] }, { key: "subtitle-1-src", value: ["data/subtitles/tumblr-de.vtt", "data/subtitles/tumblr-es.vtt"] }],
result = data.reduce((r, { key, value }) => {
let [group, i, k] = key.split('-');
if (!r[group]) r[group] = [];
if (!r[group][i]) r[group][i] = [];
value.forEach((v, j) => {
if (!r[group][i][j]) r[group][i][j] = {};
r[group][i][j][k] = v;
});
return r;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I am new to this and a beginner,
is this the correct approach?
const a = [{ "key": "path-0-mp4", "value": [ "media/video/01.mp4", "media/video/01_hd.mp4" ] }, { "key": "path-0-quality", "value": [ "720p", "1080p" ] }, { "key": "path-1-mp4", "value": [ "media/video/02.mp4", "media/video/02_hd.mp4" ] }, { "key": "path-1-quality", "value": [ "SD", "HD" ] } ];
var resp = [];
for (let i = 0; i < a.length; i++) {
var inst = a[i];
var key = inst["key"];
for (let j = 0; j < inst.value.length; j++) {
var index = key.split("-")[1];
var keyinst = key.split("-")[2];
if (!resp[index]) {
resp[index] = [];
}
if (!resp[index][j]) {
resp[index][j] = {};
}
resp[index][j][keyinst] = inst.value[j];
}
}
console.log(resp);
I find this easier to read and grasp
You can save an assignment if you use reduce
const arr = [{ "key": "path-0-mp4", "value": [ "media/video/01.mp4", "media/video/01_hd.mp4" ] }, { "key": "path-0-quality", "value": [ "720p", "1080p" ] }, { "key": "path-1-mp4", "value": [ "media/video/02.mp4", "media/video/02_hd.mp4" ] }, { "key": "path-1-quality", "value": [ "SD", "HD" ] } ];
newArr = [];
arr.filter(item => item.key.endsWith("mp4"))
.forEach(item => item.value
.forEach((val, i) => newArr.push({
"mp4": val,
"quality": arr.find(qItem => qItem.key === item.key.replace("mp4", "quality")).value[i]}
)
)
)
console.log(newArr)
Here is Nina's version in an unobfuscated version
var data = [{ key: "path-0-mp4", value: ["media/video/01.mp4", "media/video/01_hd.mp4"] }, { key: "path-0-quality", value: ["720p", "1080p"] }, { key: "path-1-mp4", value: ["media/video/02.mp4", "media/video/02_hd.mp4"] }, { key: "path-1-quality", value: ["SD", "HD"] }],
result = data.reduce((resultArray, { key, value }) => {
let [, idx, suffix] = key.split('-');
resultArray[idx] = resultArray[idx] || [];
value.forEach((val, i) => (resultArray[idx][i] = resultArray[idx][i] || {})[suffix] = val);
return resultArray;
}, []);
console.log(result);
The only odd thing I did here was using an object as a lookup table to help with the speed complexity. If you have any questions let me know.
const arr = [{ "key": "path-0-mp4", "value": [ "media/video/01.mp4", "media/video/01_hd.mp4" ] }, { "key": "path-0-quality", "value": [ "720p", "1080p" ] }, { "key": "path-1-mp4", "value": [ "media/video/02.mp4", "media/video/02_hd.mp4" ] }, { "key": "path-1-quality", "value": [ "SD", "HD" ] } ];
const result = arr.reduce((table, item) => {
// Getting "path-1" from "path-1-quality"
const pathValues = item.key.split('-');
const pathValue = pathValues[0] + '-' + pathValues[1];
// Getting "quality" from "path-1-quality"
const key = pathValues[2];
// Get Index from table if already registered paths
let tIndex = table.indexLookup[pathValue];
// If there is no registered index register one
if (tIndex === undefined) {
// reassign index to new location
tIndex = table.result.length;
// register the index
table.indexLookup[pathValue] = tIndex;
table.result.push([]);
}
// Assign values
item.value.forEach((value, i) => {
const arr = table.result[tIndex] || [];
arr[i] = arr[i] || {}
arr[i][key] = value;
table.result[tIndex] = arr;
})
return table
}, {
indexLookup : {},
result: []
}).result
console.log(result)

javascript cannot map array of objects with nested values

Trying to map array of objects with values nested in child objects structure like:
const objs = [{
"B": {
"value": 1,
},
"D": {
"value": "45"
},
"E": {
"value": "234"
},
"A": {
"value": "543"
},
"C": {
"value": "250"
}
},...]
to the structure like:
[
{ name: 'B', value: 1 },
{ name: 'D', value: '45' },
{ name: 'E', value: '234' },
{ name: 'A', value: '543' },
{ name: 'C', value: '250' }
]
and the result of the mapping is undefined
const mapped = objs.map((key, index) => {
Object.keys(key).map(el => ({
name: el
}))
})
Example: Stackblitz
You are missing return statement and value property definition.
Besides you may want to use flatMap instead of map in order to avoid a nested array in the result:
const objs = [{
"B": {
"value": 1,
},
"D": {
"value": "45"
},
"E": {
"value": "234"
},
"A": {
"value": "543"
},
"C": {
"value": "250"
}
}]
const mapped = objs.flatMap((key, index) => {
return Object.keys(key).map(el => ({
name: el,
value: key[el].value
}))
})
console.log(mapped)
You should operate on objs[0], not objs, because it is an array of one object, not array of objects.
let array = []
for(let object in objs[0]){
array.push({
"name": object,
"value": objs[0][object].value
})
}
return is missing in Object.keys. As well instead of Object.keys use Object.entries to get key and value.
const objs = [{
"B": {
"value": 1,
},
"D": {
"value": "45"
},
"E": {
"value": "234"
},
"A": {
"value": "543"
},
"C": {
"value": "250"
}
}];
const mapped = objs.map((key, _) => {
return Object.entries((key)).map(([name, {
value
}]) => ({
name,
value
}))
}).flat();
console.log(mapped);

Transform structure of array of objects

I have data like -
var data = [{"DefaultZone":[{"key":"stream0","value":100},
{"key":"stream1","value":50},
{"key":"stream2","value":10}
]},
{"Zone 1":[{"key":"stream0","value":120},
{"key":"stream1","value":55},
{"key":"stream2","value":15}
]}
]
and wanted to transform it like -
var data = [{"key": "stream0", "values":[{"x":"DefaultZone","y":100}, {"x":"Zone 1","y":120}]},
{"key": "stream1", "values":[{"x":"DefaultZone","y":50}, {"x":"Zone 1","y":55}]},
{"key": "stream2", "values":[{"x":"DefaultZone","y":10}, {"x":"Zone 1","y":15}]}
];
using JavaScript(ES6). Any help would be highly appreciated..
Here is the first way that came to mind:
var data = [{
"DefaultZone": [
{ "key": "stream0", "value": 100 },
{ "key": "stream1", "value": 50 },
{ "key": "stream2", "value": 10 }]
}, {
"Zone 1": [
{ "key": "stream0", "value": 120 },
{ "key": "stream1", "value": 55 },
{ "key": "stream2", "value": 15 }]
}];
let working = data.reduce((p, c) => {
let x = Object.keys(c)[0];
c[x].forEach(v => {
if (!p[v.key]) p[v.key] = [];
p[v.key].push({ x: x, y: v.value });
});
return p;
}, {});
let output = Object.keys(working).map(v => ({ key: v, values: working[v] }));
console.log(output);
Further reading:
the array .reduce() method
the Object.keys() method
the array .forEach() method
the array .map() method
Although I like nnnnnn's answer, here is another one, using only the Object.keys() method:
var data = [{
"DefaultZone": [{
"key": "stream0",
"value": 100
}, {
"key": "stream1",
"value": 50
}, {
"key": "stream2",
"value": 10
}]
}, {
"Zone 1": [{
"key": "stream0",
"value": 120
}, {
"key": "stream1",
"value": 55
}, {
"key": "stream2",
"value": 15
}]
}]
final = {}
data.forEach(function(x) {
Object.keys(x).forEach(function(y) {
x[y].forEach(function(z) {
if (!final[z['key']]) final[z['key']] = [];
final[z['key']].push({
'x': y,
'y': z['value']
})
})
})
})
answer = []
Object.keys(final).forEach(function(x) {
answer.push({
'key': x,
values: final[x]
})
})
console.log(answer)

Categories