Split the original array into a two-dimensional array of the specified length
list => source array
columns => columns number
targetList => two-dimensional array
const list = [1,2,3,4,5,6,7,8,9,10]
const columns = 4;
const targetList = [ [1,2,3], [4,5,6], [7,8,9], [10] ];
const columns = 5;
const targetList = [ [1,2], [3,4], [5,6], [7,8], [9,10] ];
const columns = 6;
const targetList = [ [1,2], [3,4], [5,6], [7,8], [9], [10] ];
const list = [1,2,3,4,5,6]
const columns = 4;
const targetList = [ [1,2], [3,4], [5], [6] ];
const list = [1,2,3,4]
const columns = 5;
const targetList = [ [1], [2], [3], [4] ];
You can use Array.prototype.reduce and transform the given list to the desired grid.
Push the a new row to the resultant grid if any of the following conditions meet:
If there are no rows currently.
If the last row is filled i.e. no more columns can be added to the last row, then add a new row with the current item.
If items remaining to be pushed becomes equal to rows remaining to be created.
const transform = (list, rows) =>
list.reduce((t, l, i) => {
if (
!t.length ||
t.at(-1).length >= Math.ceil(list.length / rows) ||
list.length - i === rows - t.length
) {
t.push([]);
}
t.at(-1).push(l);
return t;
}, []);
console.log(transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 4));
console.log(transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5));
console.log(transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 6));
console.log(transform([1, 2, 3, 4, 5, 6], 4));
console.log(transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 4));
console.log(transform([1, 2, 3, 4], 5));
Other relevant documentations:
Array.prototype.at
Array.prototype.push
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 am working on a problem on LeetCode and having some troubles
https://leetcode.com/problems/relative-sort-array/
Instructions:
Given two arrays arr1 and arr2, the elements of arr2 are distinct, and all elements in arr2 are also in arr1.
Sort the elements of arr1 such that the relative ordering of items in arr1 are the same as in arr2. Elements that don't appear in arr2 should be placed at the end of arr1 in ascending order.
Example 1:
Input: arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
Output: [2,2,2,1,4,3,3,9,6,7,19]
my attempt:
var relativeSortArray = function(arr1, arr2) {
let arr =[]
let end =[]
for (i=0; i<arr2.length; i++){
for (j=0; j<arr1.length; j++){
if(arr2[i] == arr1[j]){
arr.push(arr1[j])
}else{
end.push(arr1[j])
}
}
}
end.sort((a,b) => a-b)
console.log(end)
return arr
};
The If conditional works but the else condition isn't and I can't figure out why.
I think console.log(end) should give me the two numbers not in arr2 but it instead gives me:
[
1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 6,
6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 9, 9,
9, 9, 9, 19, 19, 19, 19, 19, 19
]
Why is this happening?
Thanks!!!
You could take an object for the position of a value and take a large value like Number.MAX_VALUE as default value. If the delta is zero sort by value.
Taking a delta is a standard by using Array#sort. This returns a value smaller than zero, zero or greater than zero, depending on the values. The sort method receives this values and keeps or swaps the values.
const
relativeSort = (array, given) => {
const order = Object.fromEntries(given.map((v, i) => [v, i + 1]));
return array.sort((a, b) =>
(order[a] || Number.MAX_VALUE) - (order[b] || Number.MAX_VALUE) ||
a - b
);
};
console.log(...relativeSort([2, 3, 1, 3, 2, 4, 6, 7, 9, 2, 19], [2, 1, 4, 3, 9, 6]));
In each iteration of arr2:
all the numbers that are different from the current number are pushed to the end array
For example,
First iteration - compare number (2) and you will end up with:
arr: [2,2,2]
end: [3,1,3,4,6,7,9,19]
Second iteration - compare number (1) and you will end up with:
arr: [2,2,2,1]
end: [3,1,3,4,6,7,9,19] + [2,3,3,2,4,6,7,9,2,19]
try to debug your code to follow the flow
class Solution:
def relativeSortArray(self, arr1: list[int], arr2: list[int]) -> list[int]:
arr = []
for i in arr2:
value = arr1.count(i)
for j in range(value):
arr.append(i)
arr1.remove(i)
arr1.sort()
return arr+arr1
obj = Solution()
arr1 = [28,6,22,8,44,17]
arr2 = [22,28,8,6]
result = obj.relativeSortArray(arr1,arr2)
print(result)
I'm wanting to create a function which accepts 2 arguments, first argument is an array, second argument is a number of index positions to move all the array items.
So for example if I passed exampleFunc([1,2,3,4,5], 2) it should move all items 2 places to the right, so returns [4,5,1,2,3]. I've done the following, however is there a more eloquent / efficient way of doing this? Also if I wanted to reverse the direction and condense into 1 function and not two as done below, any suggestions how to do this other than putting conditionals around the different part of each function? Tried using .splice() method but didn't really got anywhere. Any help would really be appreciated!
const moveArrayPositionRight = (array, movePositions) => {
let newArray = new Array(array.length);
for (i = 0; i < array.length; i++) {
let newIndex = i - movePositions;
if (newIndex < 0) {
newIndex += array.length;
}
newArray[i] = array[newIndex];
}
return newArray;
};
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 2)); // output: [8, 10, 2, 4, 6]
const moveArrayPositionLeft = (array, movePositions) => {
let newArray = new Array(array.length);
for (i = 0; i < array.length; i++) {
let newIndex = i - movePositions;
if (newIndex < 0) {
newIndex += array.length - 1;
}
newArray[i] = array[newIndex];
}
return newArray;
};
console.log(moveArrayPositionLeft([3, 6, 9, 12, 15], 2)); // output: [9,12,15,3,6]
You have the index of the position where you want to slice the array up and rearrange it, so you can use .slice to do exactly that - extract the sub-arrays that need to be rearranged, and put into a new array:
const moveArrayPositionRight = (array, movePositions) => [
...array.slice(array.length - movePositions),
...array.slice(0, array.length - movePositions)
];
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 2)); // output: [8, 10, 2, 4, 6]
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 3)); // expected [6, 8, 10, 2, 4]
.slice can also take negative indicies to slice an amount from the end instead of from the beginning:
const moveArrayPositionRight = (array, movePositions) => [
...array.slice(-movePositions),
...array.slice(0, -movePositions)
];
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 2)); // output: [8, 10, 2, 4, 6]
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 3)); // expected [6, 8, 10, 2, 4]
Can also use .concat instead of spread
const moveArrayPositionRight = (array, movePositions) => array
.slice(array.length - movePositions)
.concat(array.slice(0, array.length - movePositions));
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 2)); // output: [8, 10, 2, 4, 6]
console.log(moveArrayPositionRight([2, 4, 6, 8, 10], 3)); // expected [6, 8, 10, 2, 4]
Same sort of thing for moveArrayPositionLeft:
const moveArrayPositionLeft = (array, movePositions) => [
...array.slice(movePositions),
...array.slice(0, movePositions)
];
console.log(moveArrayPositionLeft([3, 6, 9, 12, 15], 2)); // output: [9,12,15,3,6]
I would like to interleave two arrays, BUT only return pairs when a certain condition is met. As an example:
first_array = [1, 2, 3, 4, 5, 6, 7, 8];
second_array = [, , , , 1, , 0, 1];
I need to return ONLY pairs where array-2 is non-null, in other words, the output I need is:
interleaved = [5, 1, 7, 0, 8, 1];
I have an interleave function that works:
function send_values() {
let interleaved = [];
for (let i = 0; i < first_array.length; i++) {
interleaved.push(first_array[i], second_array[i]);
}
}
...but the output is, obviously:
interleaved = [1, , 2, , 3, , 4, , 5, 1, 6, , 7, 0, 8, 1];
...which is not what I need. Suggestions?
You could iterate the sparse array and take only the values with the values at the same index from array one.
var array1 = [1, 2, 3, 4, 5, 6, 7, 8],
array2 = [, , , , 1, , 0, 1],
result = array2.reduce((r, v, i) => r.concat(array1[i], v), []);
console.log(result);
Here's a generic functional solution:
pairs = (a, b) => a.map((_, i) => [a[i], b[i]])
flat = a => [].concat(...a)
valid = x => x === 0 || Boolean(x)
array_1 = [1, 2, 3, 4, 5, 6, 7, 8];
array_2 = [ , , , , 1, , 0, 1];
result = flat(
pairs(array_1, array_2)
.filter(x => x.every(valid))
)
console.log(result)
Works both ways, that is, it doesn't matter which array contains the null values. Also, you can redefine valid if there are other things to exclude.
As a bonus, if you replace pairs with zip, you can make it work for any number of arrays.
So I have an array of ids something like this:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
I need a function that will be called like mergeArray(arr, 3), and it should return comma separated values with maximum of 3 elements like this:
const newArr = ['1,2,3', '4,5,6', '7,8,9', '10,11'];
How can I do this? If possible with ES6 functions for simpler code.
slice your array into 3 lengths arrays and directly join them
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
const mergeArray = (arr, size) => {
let res = [];
for (i = 0; i < arr.length; i += size) {
res.push(arr.slice(i, i + size).join(','));
}
return res;
}
console.log(mergeArray(arr, 3));
You can split() the array into the specific size and join() them before pushing into the resulting array:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
var i, j, newArr=[], size = 3;
for (i=0,j=arr.length; i<j; i+=size) {
newArr.push(arr.slice(i, i+size).join());
}
console.log(newArr);
One of the ways to do it is with Array.prototype.reduce and Array.prototype.map:
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
function mergeArray(arr, n) {
return arr
.reduce((all, el, i) => {
const ind = Math.floor(i/n);
all[ind] = [...all[ind] || [], el]
return all;
},[])
.map(a => a.join(','))
}
console.log(mergeArray(arr, 3));
You could join the array and match the wanted parts with a regular expression.
var data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
result = data.join(',').match(/\d+(,\d+(,\d+)?)?/g)
console.log(result);