Confused about pushing array into array, JavaScript - javascript

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);

Related

javascript calculation of person ages and heights

I need to take sum of all the person's ages and heights.
Input Array:
[
{
"personId": 1,
"ages": [
1,
4,
5
],
"heights": [
1,
1,
2
]
},
{
"personId": 2,
"ages": [
4,
2,
2
],
"heights": [
1,
4,
2
]
},
{
"personId": 2,
"ages": [
2,
1,
1
],
"heights": [
12
]
}
]
Desired Output:
[
{
"type": "ages",
"values": 22
},
{
"type": "heights",
"values": 23
}
]
My Solution (Which is working perfectly fine):
var agesTotal = 0;
var heightsTotal = 0;
var resultArr = [];
var sourceArr = [{personId: 1, ages: [1,4,5], heights: [1,1,2]}, {personId: 2, ages: [4,2,2], heights: [1,4,2]}, {personId: 2, ages: [2,1,1], heights: [12]}];
for(var i = 0; i < sourceArr.length; i++){
if(sourceArr[i].ages){
if(i == 0){
resultArr.push({
type: "ages",
values: agesTotal
});
}
for(var n = 0; n < resultArr.length; n++){
if(resultArr[n].type == "ages"){
resultArr[n].values += agesTotal + sourceArr[i].ages.reduce((partialSum, a) => parseFloat(partialSum) + parseFloat(a), 0)
}
}
}
if(sourceArr[i].heights){
if(i == 0){
resultArr.push({
type: "heights",
values: heightsTotal
});
}
for(var n = 0; n < resultArr.length; n++){
if(resultArr[n].type == "heights"){
resultArr[n].values += heightsTotal + sourceArr[i].heights.reduce((partialSum, a) => parseFloat(partialSum) + parseFloat(a), 0)
}
}
}
}
This above code of mine is producing the correct response, but it seems like so much processing and unoptimized.
What I need is the best & optimized possible solution for this operation
Without a clearly defined performance objective, it's hard to provide an answer that I feel is satisfying. However, I think this is readable, concise, and not wasteful:
function sumArrays (accumulator, obj) {
for (const [key, value] of Object.entries(obj)) {
if (!Array.isArray(value)) continue;
accumulator[key] ??= 0;
for (const n of value) accumulator[key] += n;
}
}
function getSums (array) {
const accumulator = {};
for (const obj of array) sumArrays(accumulator, obj);
return Object.entries(accumulator).map(([type, values]) => ({type, values}));
}
// Or, instead, optimized only for the input keys:
function getSumsOptimized (array, keysToSum) {
const result = keysToSum.map(type => ({type, values: 0}));
for (const obj of array) {
for (const [index, key] of keysToSum.entries()) {
for (const n of obj[key]) result[index].values += n;
}
}
return result;
}
const input = [
{ personId: 1, ages: [1, 4, 5], heights: [1, 1, 2]},
{ personId: 2, ages: [4, 2, 2], heights: [1, 4, 2]},
{ personId: 2, ages: [2, 1, 1], heights: [12 ]},
];
console.log(getSums(input));
console.log(getSumsOptimized(input, ['ages', 'heights']));
const array = [
{
"personId": 1,
"ages": [
1,
4,
5
],
"heights": [
1,
1,
2
]
},
{
"personId": 2,
"ages": [
4,
2,
2
],
"heights": [
1,
4,
2
]
},
{
"personId": 2,
"ages": [
2,
1,
1
],
"heights": [
12
]
}
]
let heightsSum = 0;
let agesSum = 0;
array.forEach(element => {
element.ages.forEach(age => {
agesSum += age;
})
element.heights.forEach(height => {
heightsSum += height;
})
})
const arr = [
{
type: 'ages',
values: agesSum
},
{
type: 'heights',
values: heightsSum
}
]
console.log(arr)

How to map array into another array of object

Json 1
{
"ordering_data": [
{
"order": 0,
"section_menu_id": 3
},
{
"order": 1,
"section_menu_id": 1
},
{
"order": 2,
"section_menu_id": 6
},
]
}
Json 2
[
3,
7,
4,
]
Expected result
{
"ordering_data": [
{
"order": 3,
"section_menu_id": 3
},
{
"order": 7,
"section_menu_id": 1
},
{
"order": 4,
"section_menu_id": 6
},
]
}
I got 2 json files. can someone tell me how to change the data structure to expected result .I have tried map but it kinda confused for me. Need some help .Thanks in advance.
You can use Array.prototype.map to accomplish this.
On Array.map, through the reference, the second param represents the current index of the array so based on that value, you can assign second array value to order key by index.
const input1 = {
"ordering_data": [
{
"order": 0,
"section_menu_id": 3
},
{
"order": 1,
"section_menu_id": 1
},
{
"order": 2,
"section_menu_id": 6
},
]
};
const input2 = [
3,
7,
4,
];
const updatedOrderingData = input1.ordering_data.map((item, index) => ({
...item,
order: input2[index]
}));
const result = {
ordering_data: updatedOrderingData
};
console.log(result);
I think you are looking for something like the below code snippet.
This assumes that both objects are of equal length, and we are modifying the original object.
First, loop the array, and replace the order in the original object with the numbers in the array.
Make it an exercise to create a new object instead of modifying the original obj1
var obj1 = {
"ordering_data": [
{
"order": 0,
"section_menu_id": 3
},
{
"order": 1,
"section_menu_id": 1
},
{
"order": 2,
"section_menu_id": 6
},
]
};
var myArray = [
3,
7,
4,
];
for(var i = 0; i<myArray.length; i++){
obj1.ordering_data[i].order = myArray[i];
}
console.log(obj1);
This might help.
j1 = {
"ordering_data": [
{
"order": 0,
"section_menu_id": 3
},
{
"order": 1,
"section_menu_id": 1
},
{
"order": 2,
"section_menu_id": 6
},
]
};
j2 = [
3,
7,
4,
]
for(i=0; i<j1.ordering_data.length; i++ ){
j1.ordering_data[i].order = j2[i]
}

matrix to array with every other row reversed

I have to convert matrix to array. For example
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ],
]
should convert to [1, 2, 3, 6, 5, 4, 7, 8, 9 ].
I write a code
function sortMatrix (matrix) {
let newArr = [];
for(let i = 0; i < matrix.length; i++)
{
newArr = newArr.concat(matrix[i]);
}
return newArr
}
but output is [1, 2, 3, 4, 5, 6, 7, 8, 9 ]. How can I do so that on the second line, it counts from the end
To fix your code - reverse sub-arrays at odd indexes.
Note: since Array.reverse() mutates the original array, we need to shallow clone it using array spread.
function sortMatrix(matrix) {
let newArr = [];
for (let i = 0; i < matrix.length; i++) {
const arr = matrix[i];
newArr = newArr.concat(i % 2 ? [...arr].reverse() : arr);
}
return newArr;
}
const matrix = [
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ],
];
const result = sortMatrix(matrix);
console.log(result);
Another option is to use Array.flatMap(), and reverse sub-arrays at odd indexes.
function sortMatrix(matrix) {
return matrix.flatMap((arr, i) => i % 2 ? [...arr].reverse() : arr);
}
const matrix = [
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ],
];
const result = sortMatrix(matrix);
console.log(result);
You can use reduce to create it.
const arr = [
[1,2,3],
[4,5,6],
[7,8,9]
]
const flatArray = (arr) => arr.reverse().reduce((acc, curr)=> {
acc.push(...curr.reverse());
return acc;
},[])
console.log(flatArray(arr))
You can directly use the flat function
array = [
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ],
]
console.log(array.flat());

How to arrange items in an array in all possible ways?

Items in an array can be arranged in ascending order using sort() method in JavaScript but how to arrange them in all possible ways and show them in our web page.
You describe permutations, one way to implement it:
function permutations(arr, r=[]) {
if (arr.length === 0) {
console.log(r)
} else {
const first = arr[0]
for (let i = 0; i <= r.length; i++) {
permutations(arr.slice(1), r.slice(0, i).concat([first]).concat(r.slice(i)))
}
}
}
permutations([1, 2, 3])
OUTPUT
[ 3, 2, 1 ]
[ 2, 3, 1 ]
[ 2, 1, 3 ]
[ 3, 1, 2 ]
[ 1, 3, 2 ]
[ 1, 2, 3 ]

javascript: Trying to flatten array only one level

I am trying to write a function to flatten an array. I have part of the function working and I need help in the other half.
flatten: function(anyArray, singleLevel) {
if (singleLevel == true) {
flatArray = Array.prototype.concat.apply([], anyArray);
return flatArray;
}
flatArray = Array.prototype.concat.apply([], anyArray);
if (flatArray.length != anyArray.length) {
flatArray = someObject.array.flatten(flatArray);
}
return flatArray;
}
if I type
.flatten([[[1],[1,2,3,[4,5],4],[2,3]]], true);
I want it to flatten only one level:
[[1],[1,2,3,[4,5],4],[2,3]]
Modern JavaScript allows us to handle this very easily using a variety of techniques
Using Array.prototype.flat -
const arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
const flatArr =
arr.flat(1) // 1 is default depth
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
Using Array.prototype.flatMap -
const arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
const flatArr =
arr.flatMap(x => x)
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
Using a spread argument to Array.prototype.concat
const arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
const flatArr =
[].concat(...arr)
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
Older version of JavaScript (ECMAScript 5 and below) can use techniques like Function.prototype.apply -
var arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
var flatArr =
Array.prototype.concat.apply([], arr)
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
Using Array.prototype.reduce -
var arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
var flatArr =
arr.reduce((r, a) => r.concat(a), [])
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
Using a primitive for loop -
var arr =
[ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
var flatArr =
[]
for (var i = 0; i < arr.length; i = i + 1)
flatArr = flatArr.concat(arr[i])
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]
The concat array method expects one or more arrays as arguments, whose elements will be appended:
[1].concat([2, 3], [4]) // [1, 2, 3, 4]
So if you are using apply, that will flatten another level:
[].concat.apply([1], [[2], [3]]) // === [1].concat([2], [3])
So you can either use push instead of concat, or call (or just direct invocation) instead of apply to get only a single flattening level.
if you use ES6/ES2015 you can use spread operator. Something like this
console.log(...[[[1],[1,2,3,[4,5],4],[2,3]]])

Categories