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 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/
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);
I want to sort a Array in custom way
Given arary:
arry = [0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,21,21,22,22,23,23]
Expected output:
[21,22,22,23,23,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18]
You could check the value first and the sort number greater than 20 first.
var array = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 21, 21, 22, 22, 23, 23],
predicate = function (v) { return v > 20; };
array.sort(function(a, b) {
return predicate(b) - predicate(a) || a - b;
});
console.log(array);
In javascript I have an array as follows:
var foo = [2, 2, 4, 4, 128, 2, 2, 1, 4, 18, 27, 16, 2, 1, 18, 21, 5, 1, 128, 1, 2, 2, 1, 18, 12, 60, 2, 28, 1, 17, 2, 3, 4, 2, 2, 2, 1, 27, 2, 17, 7, 2, 2, 2, 5, 1, 2, 4, 7, 1, 2, 1, 1, 1, 2, 1, 5, 7, 2, 7, 6, 1, 7, 1, 5, 8, 4];
And I am interested in finding a way (within one loop, not multiple) to derive a subset array of the highest 10 values, where the previous position of the value is the 'key' (so simulating a Map object):
eg:
var fooTopTen = [[4, 128], [18, 128], [25, 60], [27, 28], [10, 27], [37, 27], [15, 21], [9, 18], [14, 18], [23, 18]];
My previous answer used a reverse index table, but contained some bugs - which are now fixed - and was harder to understand than the following code.
This is actually the slowest of all solutions given in the answers - for maximum performance, check my other answer.
var foo = [2, 2, 4, 4, 128, 2, 2, 1, 4, 18, 27, 16, 2, 1, 18, 21, 5, 1, 128, 1, 2, 2, 1, 18, 12, 60, 2, 28, 1, 17, 2, 3, 4, 2, 2, 2, 1, 27, 2, 17, 7, 2, 2, 2, 5, 1, 2, 4, 7, 1, 2, 1, 1, 1, 2, 1, 5, 7, 2, 7, 6, 1, 7, 1, 5, 8, 4];
var fooTopTen = [];
// add index to values
for(var i = 0, len = foo.length; i < len; ++i)
fooTopTen.push([i, foo[i]]);
// sort first by value (descending order), then by index (ascending order)
fooTopTen.sort(function(t1, t2) {
return t2[1] - t1[1] || t1[0] - t2[0];
});
// shorten array to correct size
fooTopTen.length = 10;
// output top ten to check result
document.writeln('[[' + fooTopTen.join('], [') + ']]');
The second part of the comparison function (the one comparing the indices) is not needed, as sort() is stable in most implementations (this isn't required by ECMA according to MDC). I'll leave it in as an example to how sorting with multiple requirements can be done...
This runs once through the main array it searches, inserting items at the appropriate place in the results array:
function top10(arr) {
var results = [[0,Number.MAX_VALUE],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]];
for (var i=0; i<arr.length; i++) {
// search from back to front
for (var j=9; j>=0; j--) {
if (arr[i] <= results[j][1]) {
if (j==9)
break;
results.splice(j+1, 0, [i, arr[i]]);
results.pop();
break;
}
}
}
return results.slice(1);
}
For large arrays this should even be rather fast, since most times the inner loop should only do one iteration.
Here's the de-bugged version of my previous answer using an index table. I did a little benchmarking and for the input given in the question, this solition will be faster than anything else which has been suggested in this thread till now:
var foo = [2, 2, 4, 4, 128, 2, 2, 1, 4, 18, 27, 16, 2, 1, 18, 21, 5, 1, 128, 1, 2, 2, 1, 18, 12, 60, 2, 28, 1, 17, 2, 3, 4, 2, 2, 2, 1, 27, 2, 17, 7, 2, 2, 2, 5, 1, 2, 4, 7, 1, 2, 1, 1, 1, 2, 1, 5, 7, 2, 7, 6, 1, 7, 1, 5, 8, 4];
var indexTable = {}, uniqueValues = [];
// --- build reverse index table, find unique values
for(var i = foo.length; i--; ) {
var value = foo[i];
if(indexTable.hasOwnProperty(value))
indexTable[value].push(i);
else {
indexTable[value] = [i];
uniqueValues.push(value);
}
}
// --- sort unique values in ascending order
uniqueValues.sort(function(i1, i2) {
return i1 - i2;
});
// --- find ten greatest values
var fooTopTen = [], k = 0;
for(var i = uniqueValues.length; k < 10 && i--; ) {
var value = uniqueValues[i],
indices = indexTable[value];
for(var j = indices.length; k < 10 && j--; )
fooTopTen[k++] = [indices[j], value];
}
// --- output result
document.writeln('[[' + fooTopTen.join('], [') + ']]');
var foo = [2, 2, 4, 4, 128, 2, 2, 1, 4, 18, 27, 16, 2, 1, 18, 21, 5, 1, 128, 1, 2, 2, 1, 18, 12, 60, 2, 28, 1, 17, 2, 3, 4, 2, 2, 2, 1, 27, 2, 17, 7, 2, 2, 2, 5, 1, 2, 4, 7, 1, 2, 1, 1, 1, 2, 1, 5, 7, 2, 7, 6, 1, 7, 1, 5, 8, 4];
var index = 0;
var result = foo.map( function(a){ return [index++, a]; } )
.sort( function(a,b){ return (a[1] < b[1]); } )
.splice( 0, 10 );
document.write(result.join( ' ' ));
If foo is very large compared to the size of result required, it may be quicker to iterate over foo insertion-sorting each element into result as we come across it.
// Sorting method
function sortNumber(a, b) {
return a - b;
}
// Find the offset of an element in array
function findOffset(element, array) {
for (var i = 0; i < array.length; i++) {
if (array[i] == element) {
// Make sure we don't find it again
array[i] = null;
return i;
}
}
}
var foo = [2, 2, 4, 4, 128, 2, 2, 1, 4, 18, 27, 16, 2, 1, 18, 21, 5, 1, 128, 1, 2, 2, 1, 18, 12, 60, 2, 28, 1, 17, 2, 3, 4, 2, 2, 2, 1, 27, 2, 17, 7, 2, 2, 2, 5, 1, 2, 4, 7, 1, 2, 1, 1, 1, 2, 1, 5, 7, 2, 7, 6, 1, 7, 1, 5, 8, 4];
// Copies
var bar = foo.slice();
var baz = foo.slice();
var fooTopTen = new Array(10);
// Sort
bar.sort(sortNumber).reverse();
// Create the results
for (var i = 0; i < 10; i++) {
fooTopTen[i] = new Array(2);
fooTopTen[i][0] = findOffset(bar[i], baz);
fooTopTen[i][1] = bar[i];
}
computer-science-y answer:
problem statement: Given a large array X of length N, and a small number m < N (here m=10), produce an array Y of length m where each element of Y contains the pair {i,X[i]} such that the set of X{i} are the m largest elements of X.
If m is much smaller than N, then loop over elements of X and sort them into Y, discarding pairs to maintain at most m elements. (i.e. as moonshadow mentioned)
Sorting X will cost you O(N log N) elements. Iterating over X and sorting into Y should cost you only O(N log m) elements.