If I have an array of items, such as,
const array = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 ]
How can I map it, so that the screen/page renders,
1 6 11 16
2 7 12 17
3 8 13 18
4 9 14
5 10 15
I was able to get it to kind of work horizontally with,
const chunkSize = 5;
array
.map((e, i) => {
return i % chunkSize === 0 ?
selected.slice(i, i + chunkSize)
: null;
})
.filter(e => e);
But I am unable to get it to work vertically. How can I do this?
Edit:
The suggested solution from another answer returns subarrays, which is not what I had asked in this question.
You could calculate the index for the row.
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18],
chunk = 5,
result = array.reduce((r, v, i) => {
(r[i % chunk] = r[i % chunk] || []).push(v);
return r;
}, []);
result.forEach(a => console.log(...a));
const array = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 ]
const chunkSize = 5;
let result = [];
for (let i = 0; i < chunkSize; i++) {
result[i] = [];
}
array.forEach((e,i) => {
result[i % chunkSize].push(e);
});
console.log(result);
/*
Result :
[ [ 1, 6, 11, 16 ],
[ 2, 7, 12, 17 ],
[ 3, 8, 13, 18 ],
[ 4, 9, 14 ],
[ 5, 10, 15 ] ]
*/
Here's a still-compact but readable version.
const columnize = (items, rows) => {
const toColumns = (table, item, iteration) => {
let row = iteration % rows;
table[row] = table[row] || [];
table[row].push(item);
return table;
};
return items.reduce(toColumns, []);
};
Which would be used as:
const numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 ];
console.log(columnize(numbers, 5));
https://jsfiddle.net/69fshprq/
Here is a way to output it as the questions asks. I'm not paying strict attention to the spacing, I'll leave that to a string padding function or technique to implement.
const numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 ]
// <pre id="out"></pre>
let out = document.getElementById('out')
let list = columnize(numbers, 5)
for (var column in list) {
var item = list[column]
var line = item.reduce((line, item) => line + item + ' ', '')
out.textContent += line + ' \n'
}
https://jsfiddle.net/t60rfcpe/
Related
How to divide this array:- [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15] into two different arrays with one set of consecutive sequences in one array and another set of consecutive in another array.
for eg : array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15]
Desired output [0, 1, 2, 3, 4, 5, 6, 7, 8] and [12, 13, 14, 15]
The array should split into a number of consecutive sequences present in the array. If there are 3 consecutive sequences then the array should split into 3 different arrays with consecutive values and so on.
Another example = [1 ,2 ,3 ,4 5, 14, 15, 16, 22, 23, 24, 25]
Desired output [1, 2, 3, 4, 5] and [14, 15, 16] and [22, 23, 24, 25]
let arrnew = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 13, 14, 15]
let arr2 = []
for (let j = 0; j < arrnew.length; j++) {
if (arrnew[j + 1] - 1 === arrnew[j]) {
arr2.push(arrnew[j])
}
}
Tried this but not working.
var arr = [1,2,3,4,6,7,8,9,10]
var result = []
for (var i = 0; i < arr.length; i++) {
if (i === 0) {
result.push([arr[0]])
} else if (arr[i] != arr[i-1] + 1) {
result.push([arr[i]])
} else {
tmp = result[result.length - 1]
tmp.push(arr[i])
result[result.length - 1] = tmp
}
}
console.log(result) // [ [ 1, 2, 3, 4 ], [ 6, 7, 8, 9, 10 ] ]
Here we loop through arr. For the first element, the only thing we need to do is append to result a new array with the first number.
Now, for every number after the first one, if the current number is not equal to the previous number + 1, we need to append a new array to result that contains the current number. Otherwise, we simply append the current number to the last array in result.
const arr = [1, 2, 3, 4, 5, 14, 15, 16, 22, 23, 24, 25];
const canSplit = (arr = []) => {
const count = arr.reduce((acc, num) => {
acc[num] = (acc[num] || 0) + 1
return acc
}, {})
const needed = {}
for (const num of arr) {
if (count[num] <= 0) {
continue
}
count[num] -= 1
if (needed[num] > 0) {
needed[num] -= 1
needed[num + 1] = (needed[num + 1] || 0) + 1
} else if (count[num + 1] > 0 && count[num + 2]) {
count[num + 1] -= 1
count[num + 2] -= 1
needed[num + 3] = (needed[num + 3] || 0) + 1
} else {
return false
}
}
return true
}
console.log(canSplit(arr));
So I have two sets of Array, one of them is an object (arrA). And another one is just a set of primitive values arrB.
let a = "100229265852737908723455202093346882084130103685642861644052656467061936958706";
let arrA = [];
let arrB = [];
for (let i = 1; i <= 28; i++) {
arrA.push({index: i, pos: i, unique: false});
arrB.push(i);
}
let b = a.split(/(?=(?:..)*$)/).slice(0, 28);
b.forEach((val, index) => {
let c = Math.floor((+val / 100) * 28 ) + 1;
if (arrB.indexOf(c) !== -1) {
arrB.splice(arrB.indexOf(c), 1);
arrA[index].unique = true;
}
arrA[index].pos = c;
});
arrB.forEach((val, index) => {
arrA.forEach((valA, indexA) => {
if (!valA.unique) {
if (arrB[index] > valA.pos) {
arrA[indexA].pos = arrB[index];
arrA[indexA].unique = true;
arrB.splice(arrB.indexOf(arrB[index]));
}
}
})
});
My expected result is, arrA.pos is:
3, 1, 9, 8, 17, 15, 21, 4, 22, 10, 16, 6, 7, 27, 13, 20, 25, 5, 12, 14, 19, 11, 24, 18, 26, 28, 2
However I got:
3, 1, 9, 8, 17, 15, 21, 4, 21, 10, 16, 6, 6, 27, 10, 20, 23, 3, 12, 9, 3, 11, 24, 18, 8, 18, 18
If your goal is to take the string, split it into an array of elements of an arbitrary length, each being a 2-digit number, then output an Array that contains only the original Array's unique values, then you can do this:
const MAGIC_NUMBER = 28;
const a = "100229265852737908723455202093346882084130103685642861644052656467061936958706";
const b = a.split(/(?=(?:..)*$)/).slice(0, MAGIC_NUMBER );
const unique = Array.from( new Set( b ));
Set at MDN
If my Array1 is
Array1 = [1,2,3,4,5,6,7,8,9,10]
the Result should be the same as Combined_Array= [1,2,3,4,5,6,7,8,9,10]
if i got
Array2=[11,12,13,14,15,16,17,18,19,20]
the Resut should be Combined_Array =[1,2,3,4,5,11,12,13,14,15]
and if again i got
Array3=[21,22,23,24,25,26,27,28,19,30]
The Combined_array = [1,2,3,11,12,13,21,22,23,24]
and so on , Doesnt matter how much Array's i want that it should give me a Combined_Array from all the different Array with Fixed Length
Need a Function to make this work .
You could take a closure over the collected arrays and retuen an array of the parts which are difined by the count of arrays.
const
getCombined = (a) => {
const allArrays = [];
return (b => {
allArrays.push(b);
let i = 0,
p = Math.floor(10 / allArrays.length),
result = [];
while (i < allArrays.length) result.push(...allArrays[i++].slice(0, p));
while (result.length < 10) result.push(allArrays[allArrays.length - 1][p++]);
return result;
});
};
var c = [],
add = getCombined(c);
c = add([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
console.log(...c); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
c = add([11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
console.log(...c); // [1, 2, 3, 4, 5, 11, 12, 13, 14, 15]
c = add([21, 22, 23, 24, 25, 26, 27, 28, 29, 30]);
console.log(...c); // [1, 2, 3, 11, 12, 13, 21, 22, 23, 24]
You need to consider many corner cases (if result array length exceeds given arrays count, if given arrays length differs and so on).
This will work for the simple scenario:
const arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const arr2 = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
const arr3 = [21, 22, 23, 24, 25, 26, 27, 28, 19, 30];
const combineArrays = (arr, length) => {
let elementsCount = Math.floor(length / arr.length);
const result = arr.reduce((acc, el) =>
acc.concat(el.slice(0, elementsCount)), []);
while (result.length < length)
result.push(...arr.pop().slice(elementsCount, ++elementsCount));
return result;
};
const result1 = combineArrays([arr1], 10); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const result2 = combineArrays([arr1, arr2], 10); // [1, 2, 3, 4, 5, 11, 12, 13, 14, 15]
const result3 = combineArrays([arr1, arr2, arr3], 10); // [1, 2, 3, 11, 12, 13, 21, 22, 23, 24]
I have an array [1, 5, 20, 17, 6, 12, 13, 20, 1, 14, 20].
Whenever the element of the array is equal to 20 I would like to wrap it with an asterisk on either side like this [1, 5, *20*, 17, 6, 12, 13, *20*, 1 , 14, *20*].
How can I achieve this?
You can use map
let arr = [1, 5, 20, 17, 6, 12, 13, 20, 1, 14, 20]
let result = arr.map(o => o === 20 ? '*20*' : o);
console.log(result);
Doc: map()
You can use Arrays forEach to modify the elements of the array. elem is each element and i is the respective index. We are using forEach to modify the existing array. Since this is what you desired..
let arr = [1, 5, 20, 17, 6, 12, 13, 20, 1, 14, 20]
arr.forEach((elem, i) => {
if (elem === 20) {
arr[i] = "*20*"
}
})
console.log(arr)
function rollDice(max, times, bonus) {
var rolls = [1, 5, 20, 17, 6, 12, 13, 20, 1, 14, 20];
rolls.forEach((elem, i) => { if (elem === 20) { rolls[i] = "twenty" } });
for (var i = 0; times > i; i++)
{
max = Math.floor(max);
rolls.push(Math.floor(Math.random() * max) + 1 | + parseInt(bonus));
}
console.log(rolls);
}
rollDice(20, 5);
The problem you are experiencing is that you need to convert the integer number into strings. JavaScript has several ways to cleverly do this behind-the-scenes, but if you are still gaining an understanding of that, it's better to be explicit about what data types you start with (integers), and what data types you expect to end with (strings).
You transform the array, "mapping" over each item, transforming it to a string, and then if the string matches "20", you add the asterisks.
const start_array = [1, 5, 20, 17, 6, 12, 13, 20, 1, 14, 20];
const new_array = start_array.map((integer) => {
let number_string = integer.toString();
if (number_string === "20") {
number_string = "*" + number_string + "*";
}
return number_string;
})
console.log(new_array);
My purpose is to create a function that removes elements from an array to reduce its length to the desired length.
But the condition is that it should remove the elements at (almost) equal interval. And the function should work for any value of array.length and desired_length.
For example:
myArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
desired_length = 7;
myFunction( myArray, desired_length ) //returns [0, 4, 7, 10, 13, 16, 19]
It does not matter which elements are removed. But if we plot the elements of returned array on a line chart, then the line should be as smooth as possible.
Use Case:
I have an array which contains images. I want to render them as GIF of fixed number of frames. So if there are 100 images in the array, I want to remove some images from between so the array has only 20 images. Now the important part is to remove frames at equal interval so the final animation is as little jerky as possible. The length of the array can vary each time.
You could use the remainder operator and check for zero with the division of the length of the aaray and the wanted length.
function getArray(array, length) {
return array.filter(function (_, i, a) {
return !(i % (a.length / length));
});
};
var myArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
console.log(getArray(myArray, 10)); // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
console.log(getArray(myArray, 5));
.as-console-wrapper { max-height: 100% !important; top: 0; }
The important thing is the calculation of step which can be used to iterate over the original array.
EDIT: adding Math.round makes the code work for length / desired_length != 0. Your desired output is hard to reproduce in my eyes.
myArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
console.log(myFunction( myArray, 10 )) // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
console.log(myFunction( myArray, 5 )) // [0, 4, 8, 12, 16]
console.log(myFunction( myArray, 7 )) // [0, 3, 6, 9, 12, 15, 18]
function myFunction( arr, desired_length) {
var arr_length = arr.length;
var step = Math.round(arr_length / desired_length);
var new_arr = [];
for (var i = 0; i < arr_length; i += step) {
new_arr.push(arr[i]);
}
return new_arr;
}
Solution:
// always saves first and last element
function setMaxElements( array, max_elements ) {
if( array.length > max_elements ) {
// Always save first element
var new_array = [ array[0] ];
// index of last saved element
var last_saved_element = 0;
for( var i = 1; i < array.length; i++ ) {
// (array.length-1) & (max_elements-1) because we already saved one element
var element_group = Math.floor( i / ( array.length - 1 ) * ( max_elements - 1 ) );
if( last_saved_element < element_group ) {
new_array.push( array[i] );
last_saved_element = element_group;
}
}
return new_array;
} else {
return array;
}
}
myArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
console.log( setMaxElements( myArray, 13 ) ); // [0, 2, 4, 5, 7, 8, 10, 12, 13, 15, 16, 18, 19]
console.log( setMaxElements( myArray, 10 ) ); // [0, 3, 5, 7, 9, 11, 13, 15, 17, 19]
console.log( setMaxElements( myArray, 07 ) ); // [0, 4, 7, 10, 13, 16, 19]
console.log( setMaxElements( myArray, 03 ) ); // [0, 10, 19]
For my use case I decided to keep the first and last element and remove from the rest. If that is not a constraint for you, then you can also use this function:
// always saves first element but may remove the last element
function setMaxElements( array, max_elements ) {
if( array.length > max_elements ) {
var new_array = [];
var last_saved_element = -1 ;
for( var i = 0; i < array.length; i++ ) {
var element_group = Math.floor( i / array.length * max_elements );
if( last_saved_element < element_group ) {
new_array.push( array[i] );
last_saved_element = element_group;
}
}
return new_array;
} else {
return array;
}
}
myArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
console.log( setMaxElements( myArray, 13 ) ); // [0, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19]
console.log( setMaxElements( myArray, 10 ) ); // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
console.log( setMaxElements( myArray, 07 ) ); // [0, 3, 6, 9, 12, 15, 18]
console.log( setMaxElements( myArray, 03 ) ); // [0, 7, 14]
I put the values in excel to understand how to create the formula.
Final result
As you can see, The function converts the array of any length to the desired length.