Related
I have a data structure as follows:
UPDATED: to have more than one object in innerValues
const data = {
"dates": [
"2015-09-09T00:00:00",
"2015-09-09T00:10:00",
"2015-09-09T00:20:00",
],
"innerValues": [
{
"name": "Name_1",
"value": [
104,
105,
107,
]
},
{
"name": "Name_2",
"value": [
656,
777,
145,
]
}],
}
I would like to create an output like:
const outPut = [
["2015-09-09T00:00:00", 'Name_1', 104 ],
["2015-09-09T00:10:00", 'Name_1', 105 ],
["2015-09-09T00:20:00", 'Name_1', 107 ],
["2015-09-09T00:00:00", 'Name_2', 104 ],
["2015-09-09T00:10:00", 'Name_2', 105 ],
["2015-09-09T00:20:00", 'Name_2', 107 ]
]
So far I have this, I know I could do this with forEach etc also - but as an example.
const m = data.dates;
let arr = [];
for (var i = 0; i < m.length; i++) {
arr[i] = new Array(m[i]);
}
console.log(arr);
This gives:
0: ['2021-09-09T00:00:00']
1: ['2021-09-09T00:10:00']
2: ['2021-09-09T00:20:00']
Which is where I want to start, however if I map over inner.values and try to create an new array from that, it does not return three separate arrays but one.e.g
const newArray = x.forEach(inner => console.log(new Array(inner)))
Output
0: (3) [104, 105, 107]
How could I achieve the above desired structure.
You can use reduce and map to loop over innerValues and their values
const dates = data.dates
const newArr = data.innerValues.reduce((acc, cur, i) => {
acc.push(cur.value.map((value, i) => ([dates[i], cur.name, value])));
return acc;
}, []).flat()
console.log(newArr)
<script>
const data = {
"dates": [
"2015-09-09T00:00:00",
"2015-09-09T00:10:00",
"2015-09-09T00:20:00",
],
"innerValues": [{
"name": "Name_1",
"value": [
104,
105,
107,
]
},
{
"name": "Name_2",
"value": [
656,
777,
145,
]
}
],
}
</script>
My code looks like this
var res = [];
var temp = [];
function Permutations(target, size) {
if (size === 0) {
res.push(temp);
console.log(res);
return;
}
for (let i = 0; i < target.length; i++) {
if (target[i] !== null) {
temp.push(target[i]);
target[i] = null;
Permutations(target, size - 1);
target[i] = temp.pop();
}
}
}
Permutations([1, 2, 3], 2);
console.log(res);
When I run my code, I can see my res stores each permutation as it is is being executed. However, when I log it outside the function, all the stored value disappeared.
[ [ 1, 2 ] ]
[ [ 1, 3 ], [ 1, 3 ] ]
[ [ 2, 1 ], [ 2, 1 ], [ 2, 1 ] ]
[ [ 2, 3 ], [ 2, 3 ], [ 2, 3 ], [ 2, 3 ] ]
[ [ 3, 1 ], [ 3, 1 ], [ 3, 1 ], [ 3, 1 ], [ 3, 1 ] ]
[ [ 3, 2 ], [ 3, 2 ], [ 3, 2 ], [ 3, 2 ], [ 3, 2 ], [ 3, 2 ] ]
[ [], [], [], [], [], [] ] // This is my console.log outside the function
The array temp holds is the same array throughout the complete execution of your code. And res.push(temp); adds this same array (not a copy of it) to your res array.
Here a related question about how Objects are handled in JavaScript: Is JavaScript a pass-by-reference or pass-by-value language?
So your code results in res having N times the same array.
You could copy the element stored in temp to a new array using [...temp], and push that to your res array.
var res = [];
var temp = [];
function Permutations(target, size) {
if (size === 0) {
res.push([...temp]);
return;
}
for (let i = 0; i < target.length; i++) {
if (target[i] !== null) {
temp.push(target[i]);
target[i] = null;
Permutations(target, size - 1);
target[i] = temp.pop();
}
}
}
Permutations([1, 2, 3], 2);
console.log(res);
I have an array of objects of the structure coming from server response of iterated array object like as sample
var arrObj1 = [
{"id":"1","value":21, "value1":13},
{"id":"2","value":21, "value1":13 },
......n
];
var arrObj2 = [
{"id":"1","value3":21, "value14":13},
{"id":"2","value3":21, "value4":13 },
......n
];
var arrObj3 = [
{"id":"1","value5":21, "value6":13},
{"id":"2","value5":21, "value6":13 },
......n
];
But now I want to append the array values inot single new array according to key following structure of as iterated values of above array Expected Output:
var finalObj = [
{
"id" : 1
"value" : 21,
"value1" : 13,
"value3" : 21,
"value4" : 13,
"value5" : 21,
"value6" : 13,
},
{
"id" : 2
"value" : 21,
"value1" : 13,
"value3" : 21,
"value4" : 13,
"value5" : 21,
"value6" : 13,
},
.....n
];
You can use reduce for concated arrays
const arrObj1 = [
{ id: '1', value: 21, value1: 13 },
{ id: '2', value: 21, value1: 13 },
];
const arrObj2 = [
{ id: '1', value3: 21, value14: 13 },
{ id: '2', value3: 21, value4: 13 },
];
const arrObj3 = [
{ id: '1', value5: 21, value6: 13 },
{ id: '2', value5: 21, value6: 13 },
];
const result = [...arrObj1, ...arrObj2, ...arrObj3].reduce(
(acc, { id, ...rest }) => ({ ...acc, [id]: acc[id] ? { ...acc[id], ...rest } : { ...rest } }),
{},
);
console.log(Object.entries(result).map(([id, data]) => ({ id, ...data })));
Push you arrays to a new array (you have to have your sub arrays in other list to loop through them) and then use flat, after that group your object according to the id property
var arrObj1 = [{
"id": "1",
"value": 21,
"value1": 13
},
{
"id": "2",
"value": 21,
"value1": 13
},
];
var arrObj2 = [{
"id": "1",
"value3": 21,
"value14": 13
},
{
"id": "2",
"value3": 21,
"value4": 13
},
];
var arrObj3 = [{
"id": "1",
"value5": 21,
"value6": 13
},
{
"id": "2",
"value5": 21,
"value6": 13
},
];
const input = [];
input.push(arrObj2, arrObj3);
const preResult = input.flat();
result = preResult.reduce((acc, x) => {
const index = acc.findIndex(y => y.id === x.id)
if (index >= 0) {
acc[index] = {
...acc[index],
...x
}
} else {
acc.push(x)
}
return acc;
}, arrObj1)
console.log(result)
You can iterate over array-length and push here for every entry 1 entry to the result. For getting this entry take a new object with the id and iterate over all (3 or perhaps more) arrays. For every array take the i-th entry and push for every key an entry with key:value (except for the key id itself).
Remark: You can use as much arrays you want and every object could contain as much value-prperties as you need. The only restriction is that every array has the same count of objects.
var arrObj1 = [
{"id":"1","value":21, "value1":13},
{"id":"2","value":21, "value1":13 }
];
var arrObj2 = [
{"id":"1","value3":21, "value4":13},
{"id":"2","value3":21, "value4":13 }
];
var arrObj3 = [
{"id":"1","value5":21, "value6":13},
{"id":"2","value5":21, "value6":13 }
];
let result =[];
let arrayAll = [arrObj1, arrObj2, arrObj3];
for (let i=0; i<arrayAll[0].length; i++) {
let obj = arrayAll[0][i];
let res = { id: obj.id};
for (let j=0; j<arrayAll.length; j++) {
let obj = arrayAll[j][i];
Object.keys(obj).forEach(key => {
if (key!='id') res[key] = obj[key];
})
}
result.push(res);
}
console.log(result);
Since you are using id to merge multiple objects, Map is one of the good option to merge.
let arrObj1 = [
{"id":"1","value":21, "value1":13},
{"id":"2","value":21, "value1":13 },
];
let arrObj2 = [
{"id":"1","value3":21, "value14":13},
{"id":"2","value3":21, "value4":13 },
];
let arrObj3 = [
{"id":"1","value5":21, "value6":13},
{"id":"2","value5":21, "value6":13 },
];
let mergedArray = [...arrObj1,...arrObj2,...arrObj3].reduce((acc,curr) =>{
if(acc.has(curr.id)){
acc.set(curr.id, {...acc.get(curr.id),...curr});
}else{
acc.set(curr.id,curr);
}
return acc;
},new Map())
console.log(Array.from(mergedArray,x=>x[1]));
The problem I have is, that I want to combine a 2D Array like this:
[
[ "Renault", 61, 16, … ],
[ "Ferrari", 58, 10, … ],
[ "Mercedes", 32, 12, … ],
[ "Mercedes", 24, 21, … ],
[ "Toro Rosso", 7, 8, … ]
]
So in this example I have the String "Mercedes" twice at index 0 in the arrays.
What I want the output to be is the following:
[
[ "Renault", 61, 16, … ],
[ "Ferrari", 58, 10, … ],
[ "Mercedes", 56, 33, … ],
[ "Toro Rosso", 7, 8, … ]
]
So if a String like "Mercedes" is appearing twice in that array I want the second one to be deleted. But the values from the second array must be taken over into the first "Mercedes" Array.
It seems that you actually want to aggregate similar values in the array. Therefore you could do a cycle in foreach and save yourself in a temporary array the string values already known and instead in another your merged classes. At that point, as you scroll through your array, you can check if you have already added an equal string in the first fake, and if so, you can take its index and aggregate them correctly in the other array.
let arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
]
var tmp1 = [], tmp2 = [];
arr.forEach(function(currentValue, index, arr) {
// currentValue contain your element
// index contain the index of your element
// arr contain you entire "values" array
var ind = tmp1.indexOf(currentValue[0]);
if(ind === -1) {
tmp1.push(currentValue[0]);
tmp2.push(currentValue);
} else {
tmp2[ind][1] += currentValue[1];
tmp2[ind][2] += currentValue[2];
}
});
console.log(tmp2);
You can use reduce() to build a object and then use Object.values()
const arr = [
[ "Renault", 61, 16 ],
[ "Ferrari", 58, 10],
[ "Mercedes", 32, 12],
[ "Mercedes", 24, 21],
[ "Toro Rosso", 7, 8]
]
let res = arr.reduce((ac, [k, ...rest]) => {
if(!ac[k]) ac[k] = [];
ac[k] = ac[k].concat(k,...rest);
return ac;
},[])
console.log(Object.values(res))
Sure, by creating an array for your names and then separate the unique ones from them, at last, match them with the index.
let arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
]
let c = [...new Set(arr.map(a => a[0]))] // get unique values of all arr[0]
let ans = arr.filter((a, post) => {
if (c[post]) { // check if index exists because we seperated one, the last is undefined here
if (a[0] == c[post]) {
return a;
}
} else {
return a; // else return as usual
}
})
console.log(ans)
You get the filtered array.
You can iterate over the array and keep a map object of the names you already processed with their index in the result array so you can access them quicker when you need to push more values.
i.e:
{
"Renault": 0,
"Ferrari": 1,
"Mercedes": 2,
"ToroRosso": 3
}
Here is a running example with the steps:
const arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
];
let map = {};
let globalIndex = 0;
let resultArray = [];
arr.forEach((currentArray) => {
const [name, ...rest] = currentArray;
if (map[name] === undefined) {
// if our map doesn't already store this value
// then store it with it's current index
map[name] = globalIndex;
// push it to the result array
resultArray[globalIndex] = currentArray;
// increment the global index
//so we can keep track of it in the next iteration
globalIndex++;
} else {
// we already have an array with this name
// grab the relevant index we previously stored
// and push the items without the name via this index
const relevantIdx = map[name];
resultArray[relevantIdx] = [
...resultArray[relevantIdx],
...rest
]
}
})
console.log(resultArray);
array1 = [{
"id": 1,
"name": "aaa",
},
{
"id": 2,
"name": "bbb"
},
{
"id": 5,
"name": "ccc"
},
{
"id": 6,
"name": "ddd"
},
{
"id": 8,
"name": "eee"
},
{
"id": 12,
"name": "fff"
}]
array2 = [ 5, 6, 8 ,12]
Resulting Array = [ {name: "ccc"}, {name: "ddd"} , {name: "eee"}, {name: "fff"} ]
I am looking to map both arrays to get matching id numbers and get copy the names in the resulting arrray but I didn't succeed. Can you please suggest me how to do it?
Thank you
You could try the following. Basically, you're filtering the first array based on whether or not the id exists in the 2nd array and then mapping it back by only selecting the key(s) you want.
var resultArray = array1.filter(function(arr) {
return array2.indexOf(arr.id) !== -1;
}).map(function(item) {
return {
name: item.name
};
});
Let's turn array1 into an object first, that maps ids to the corresponding objects:
var idMap = {}
array1.forEach(function(element) {
idMap[element.id] = element
})
You can then get the result you want by doing
var result = array2.map(function(id) {
return idMap[id]
});
Try This:
array1 = [{"id": 1,"name": "aaa"},{"id": 2,"name": "bbb"},{"id": 5,"name": "ccc"},{"id": 6,"name": "ddd"},{"id": 8,"name": "eee"},{"id": 12,"name": "fff"}] ;
array2 = [ 5, 6, 8 ,12];
var result = array1.filter(item => array2.includes(item.id)).map(({id,name}) => ({name}));
console.log( result );