I have an array which can be nested multiple times. However, always two arrays with two entries each are at the end of each "nesting". I always need the two entries from the two arrays at the end of each nesting returned.
Here is an example:
const arr = [
[
[1, 2], [3, 4]
], [
[5, 6], [7, 8]
], [
[
[9, 10], [11, 12]
], [
[14, 15], [16, 17]
]
]
];
Here is the expected result:
const return1 = [
{ a: 1, b: 2 },
{ a: 3, b: 4 }
];
const return2 = [
{ a: 5, b: 6 },
{ a: 7, b: 8 }
];
const return3 = [
{ a: 9, b: 10 },
{ a: 11, b: 12 }
];
const return4 = [
{ a: 13, b: 14 },
{ a: 15, b: 16 }
];
Everything I find online is how to reduce an n-nested array to a flat array, something like this:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
You could map with an iterative and recursive approach while checking nested arrays.
var array = [[[1, 2], [3, 4]], [[5, 6], [7, 8]], [[[9, 10], [11, 12]], [[14, 15], [16, 17]]]],
result = array.reduce(function iter(r, a) {
return r.concat(Array.isArray((a[0] || [])[0])
? a.reduce(iter, [])
: [a.map(([a, b]) => ({ a, b }))]
);
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
With custom recursive function:
var arr = [[[1, 2], [3, 4]], [[5, 6], [7, 8]], [[[9, 10], [11, 12]], [[14, 15], [16, 17]]]],
result = [],
get_pairs = function(arr, r){
arr.forEach(function(v){
if (Array.isArray(v)) {
if (!Array.isArray(v[0])) {
var o = {a: v[0], b: v[1]};
(!r.length || r[r.length-1].length==2)? r.push([o]) : r[r.length-1].push(o);
} else {
get_pairs(v, r);
}
}
});
};
get_pairs(arr, result);
console.log(result);
Spent to much time in this. However, here is a very messy looking code.
There is this recursive function that checks if a given array is in the form [[number, number],[number, number]]. If so, it adds an object to the variable returnArray that we are knowingly mutating.
If it is not in the form, we just check for the items inside the array.
const arrInput = [
[[1, 2], [3, 4]],
[[5, 6], [7, 8]],
[
[[9, 10], [11, 12]],
[[14, 15], [16, 17]],
],
];
function mapArrayToObj(arr, returnArray = []) {
if (arr.length === 2 && typeof arr[0][0] === "number" &&
typeof arr[0][1] === "number" && typeof arr[1][0] === "number" &&
typeof arr[1][1] === "number") {
returnArray.push([
{ a: arr[0][0], b: arr[0][1] },
{ a: arr[1][0], b: arr[1][1] }
]);
} else {
arr.forEach((item) => { mapArrayToObj(item, returnArray); });
}
return returnArray;
}
console.log(mapArrayToObj(arrInput));
Related
I'm trying to sort multiple arrays within an array (which also has to be shuffled). A simplified example is:
let toShuffle = [
[1, 2, 3, 4, 5],
[9, 8, 7, 6, 5],
[10, 67, 19 ,27]
...
];
const shuffled = shuffle(toShuffle);
// outout would look something like:
// [
// [8, 6, 5, 7, 9],
// [4, 3, 1, 5, 2],
// [19, 26, 10, 67],
// ...
// ]
This needs to be flexible, so any number of arrays with any amount of values should be valid.
Here is what I've tried:
function shuffle(a) {
for (let e in a) {
if (Array.isArray(a[e])) {
a[e] = shuffle(a[e]);
} else {
a.splice(e, 1);
a.splice(Math.floor(Math.random() * a.length), 0, a[e]);
}
}
return a;
}
console.log("Shuffled: " + shuffle([
[1, 2, 3, 4, 5],
[5, 4, 3, 2, 1]
]))
But it's not working as intended. Is their an easier way to do this? Or is my code correct and just buggy.
You can use Array.from() to create a new shallow-copied array and then to shuffle Array.prototype.sort() combined with Math.random()
Code:
const toShuffle = [
[1, 2, 3, 4, 5],
[9, 8, 7, 6, 5],
[10, 67, 19 ,27]
]
const shuffle = a => Array.from(a).sort(() => .5 - Math.random())
const result = toShuffle.map(shuffle)
console.log('Shuffled:', JSON.stringify(result))
console.log('To shuffle:', JSON.stringify(toShuffle))
You almost got it. The problem is that you are removing one item from an array, instead of capturing the removed item and them placing in a random position:
let toShuffle = [
[1, 2, 3, 4, 5],
[9, 8, 7, 6, 5],
[10, 67, 19 ,27]
];
function shuffle(a) {
a = [...a]; //clone array
for (let e in a) {
if (Array.isArray(a[e])) {
a[e] = shuffle(a[e]);
} else {
a.splice(~~(Math.random() * a.length), 0, a.splice(e, 1)[0]);
}
}
return a;
}
console.log(JSON.stringify(shuffle(toShuffle)))
console.log(JSON.stringify(toShuffle))
[EDIT]
The original code did not shuffle the parent array, if you need shuffle everything recursively, you can use this:
let toShuffle = [
[1, 2, 3, 4, 5],
[9, 8, 7, 6, 5],
[10, 67, 19 ,27]
];
function shuffle(a) {
a = a.map(i => Array.isArray(i) ? shuffle(i) : i); //clone array
a.sort(i => ~~(Math.random() * 2) - 1); //shuffle
return a;
}
console.log("shuffled", JSON.stringify(shuffle(toShuffle)))
console.log("original", JSON.stringify(toShuffle))
I have an object like this:
const object = {
detectors: [1, 2],
responders: [4, 22],
activators: [5, 23, 31],
enablers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
upgraders: [14, 15, 16, 17, 18, 19, 20, 21, 22],
catalyzer: [12, 29],
chains: [27],
trappers: [13],
finishers: [16],
}
Expected output :
[
{
'detectors': 1,
'responders': 4,
'activators': 5,
'enablers': 1,
'upgraders': 23,
'catalyzer': 12,
'chains': 27,
'trappers': 13,
'finishers': 16,
},
{
'detectors': 2,
'responders': 4,
'activators': 5,
'enablers': 1,
'upgraders': 23,
'catalyzer': 12,
'chains': 27,
'trappers': 13,
'finishers': 16,
},
{
'detectors': 1,
'responders': 22,
'activators': 5,
'enablers': 1,
'upgraders': 23,
'catalyzer': 12,
'chains': 27,
'trappers': 13,
'finishers': 16,
},
{...
And I already wrote a function like this:
object.activators.map((activator, i) => {
return object.detectors.map((detector, i) => {
return object.responders.map((responder, i) => {
return {
detectors: detector,
responders: responder,
activators: activator,
};
});
});
});
I can write another function to flatten the output of the code above, but is there any other way to write the code above into a more general function (not hardcoded) that can apply to any object?
You can use a recursive function to get all permutations from the entries.
const object = {
detectors: [1, 2, 3],
responders: [4, 22],
activators: [1, 2, 3, 4]
};
const getPermutations = obj => {
const res = [];
const entries = Object.entries(obj);
const go = (curr, idx) => {
const key = entries[idx][0];
for(const val of entries[idx][1]){
const next = {...curr, [key]: val};
if(idx !== entries.length - 1) go(next, idx + 1);
else res.push(next);
}
};
go({}, 0);
return res;
}
console.log(getPermutations(object));
I have a dictionary structure as follows :
data = { a : [5, 10], b : [1, 12] , c : [6, 7]}
I need to convert this to follows :
[ a, 5, 10 ], [ b, 1, 12 ], [ c, 6, 7 ]
I've already tried using Object.entries(data), but it returned the data like : [a, [5, 10]], [b, [1, 12]]
How can i do this using JavaScript?
You could map the key/values in a new array.
var data = { a : [5, 10], b : [1, 12] , c : [6, 7]},
result = Object.entries(data).map(([k, v]) => [k, ...v]);
console.log(result);
Another way:
const data = { a : [5, 10], b : [1, 12] , c : [6, 7]};
const result = Object.entries(data).map(pair => pair.flat());
console.log(result);
So with Object.keys() and reduce() you can solve as the following:
const data = { a: [5, 10], b: [1, 12], c: [6, 7] };
const result = Object.keys(data).map(e => {
return data[e].reduce((a, c) => {
a.push(c);
return a;
}, Array.from(e));
});
console.log(result);
I hope that helps!
var dict = { 'a': 'aa', 'b': 'bb' };
var arr = [];
for (var key in dict) {
if (dict.hasOwnProperty(key)) {
arr.push( [ key, dict[key] ] );
}
}
this might helps you out
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have multiple arrays in a main/parent array like this:
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
[2, 12],
[2, 12]
];
I have the code to select the arrays that are repeated 3 or more times (> 3) and assign it to a variable.
The code is:
var arr = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]]
arr.sort((a, b) => a[0] - b[0] || a[1] - b[1])
// define equal for array
const equal = (arr1, arr2) => arr1.every((n, j) => n === arr2[j])
let GROUP_SIZE = 3
first = 0, last = 1, res = []
while(last < arr.length){
if (equal(arr[first], arr[last])) last++
else {
if (last - first >= GROUP_SIZE) res.push(arr[first])
first = last
}
}
if (last - first >= GROUP_SIZE) res.push(arr[first])
console.log(res)
So the final result is:
console.log(repeatedArrays);
>>> [[1, 17], [2, 12]]
My problem: But the problem is, I have an array like this {from: [12, 0], to: [14, 30]}.
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
{from: [12, 0], to: [14, 5]},
{from: [12, 0], to: [14, 5]},
{from: [4, 30], to: [8, 20]},
{from: [12, 0], to: [14, 5]},
{from: [4, 30], to: [8, 20]},
[2, 12],
[2, 12]
];
When I try to use the above code, it doesn't work. The error message is:
Uncaught TypeError: arr1.every is not a function
The final result should be:
console.log(repeatedArrays);
>>> [[1, 17], [2, 12], {from: [12, 0], to: [14, 5]}]
How can I make that code above work?
If you introduce a non array into the mix, you need to handle it differently.
Yours already work with array so I'm adding object style check for both sort and equal.
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
{ from: [4, 30], to: [8, 21] },
{ from: [12, 0], to: [14, 5] },
{ from: [12, 0], to: [14, 5] },
{ from: [4, 30], to: [8, 20] },
{ from: [12, 0], to: [14, 5] },
{ from: [4, 30], to: [8, 20] },
[2, 12],
[2, 12]
];
arr.sort((a, b) => {
if (a instanceof Array && b instanceof Array) {
return a[0] - b[0] || a[1] - b[1]
} else if (a instanceof Array || b instanceof Array) {
return a instanceof Array ? -1 : 1
} else {
return a.from[0] - b.from[0] || a.from[1] - b.from[1] || a.to[0] - b.to[0] || a.to[1] - b.to[1]
}
});
// define equal for array
const equal = (arr1, arr2) => {
if (arr1 instanceof Array) {
return arr1.every((n, j) => n === arr2[j]);
} else {
if (arr2 instanceof Array) return false;
for (let k in arr1) {
if (!arr1[k].every((n, j) => n === arr2[k][j])) {
return false
}
}
return true;
}
};
let GROUP_SIZE = 3;
(first = 0), (last = 1), (res = []);
while (last < arr.length) {
if (equal(arr[first], arr[last])) last++;
else {
if (last - first >= GROUP_SIZE) res.push(arr[first]);
first = last;
}
}
if (last - first >= GROUP_SIZE) res.push(arr[first]);
console.log(res);
You can use the function reduce for grouping and counting the objects and then execute the function filter for getting the object with count >= 3.
var array = [ [1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12], [2, 12] ];
let result = Object.values(array.reduce((a, [c, b]) => {
let key = `${c}|${b}`;
(a[key] || (a[key] = {count: 0, value: [c, b]})).count++;
return a;
}, {})).filter(o => {
if (o.count >= 3) {
delete o.count;
return true;
}
return false;
}).map(({value}) => value);
console.log(result);
.as-console-wrapper { min-height: 100%; }
Really simple - filter it all, then remove duplicates with Set and JSON methods (because it's nested arrays not objects):
var array = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
[2, 12],
[2, 12]
];
var repeatedArrays = [...new Set(array.filter(e => array.filter(f => JSON.stringify(e.sort()) == JSON.stringify(f.sort()))).map(JSON.stringify))].map(JSON.parse);
console.log(repeatedArrays);
I try to loop the 2d arrays, but the I variable is undefined or not iterable, why?
can anyone tell me ??
function sum (arr) {
var total = 0
for(let [a1,a2,a3] of arr){
for(let i of [a1,a2,a3]){
for(let j of i){
total += j
}
}
if(typeof a2 == "undefined" && typeof a3 == "undefined"){
a2 = [0]
a3 = [0]
}
}
};
console.log(sum([
[
[10, 10],
[15],
[1, 1]
],
[
[2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[4],
[9, 11]
],
[
[3, 5, 1],
[1, 5, 3],
[1]
],
[
[90]
]
]));
but when i sum another 2D array, it works, like this :
function sum (arr) {
var total = 0
for(let [a1,a2,a3] of arr){
for(let i of [a1,a2,a3]){
for(let j of i){
total += j
}
}
}
return total
}
console.log(sum([
[
[4, 5, 6],
[9, 1, 2, 10],
[9, 4, 3]
],
[
[4, 14, 31],
[9, 10, 18, 12, 20],
[1, 4, 90]
],
[
[2, 5, 10],
[3, 4, 5],
[2, 4, 5, 10]
]
]));
i try to loop 3 times for this 2d arrays, the first top code is each lengths are diffreen in array
and the last code is same,
Cause
let [a1,a2,a3] of [ [90] ])
will result in a2 and a3 being undefined, therefore in the following line it is:
for(const i of [90, undefined, undefined])
And at the second index it does:
for(let j of undefined)
which doesnt work.
You just need to move your if statement that checks if the value is undefined and assigns it to zero if it is ahead of the part of code that iterates over those values. You were getting this error because there wasn't anything there.
function sumTwo(arr) {
var total = 0
for(let [a1,a2,a3] of arr){
if(typeof a2 == "undefined" && typeof a3 == "undefined"){
a2 = [0]
a3 = [0]
}
for(let i of [a1,a2,a3]){
for(let j of i){
total += j
}
}
}
return total
};
console.log(sumTwo([
[
[10, 10],
[15],
[1, 1]
],
[
[2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[4],
[9, 11]
],
[
[3, 5, 1],
[1, 5, 3],
[1]
],
[
[90]
]
])); //prints 237
When you say
let [a1,a2,a3] of [ [90] ])
there is no a2 or a3 there...
My suggestion would be using the code before you get into the first for loop:
if(arr.length < 3){
for(let y = arr.length, y > 3, y++ ){
arr.push(0)
}
}
Cheers!
It's probably better to recursively reduce the array using concat until you have a flat array and then reduce that to the sum of it's numbers:
const arr = [
[[10, 10], [15], [1, 1]],
[[2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [4], [9, 11]],
[[3, 5, 1], [1, 5, 3], [1]],
[[90]],
];
const flatten = (arr) => {
const recur = (result, item) =>
!Array.isArray(item)
? result.concat(item)
: result.concat(item.reduce(recur, []));
return arr.reduce(recur, []);
};
console.log(
flatten(arr).reduce((result, item) => result + item, 0),
);