Replicate array to certain length in javascript - javascript

I have this array [1,2,3]
I would like to be able to set its length to 7
and have this [1,2,3,1,2,3,1] as a result.
Anyone?
const arr = [1,2,3];
// Something like
arr.resize(7);
console.log(arr); // [1,2,3,1,2,3,1]
EDIT:
Based on chevybow answer below i wrote this functions to serve my needs.
// Immutable
Array.prototype.resize = function(size) {
const array = Array(size);
for(let i = 0; i < size; i++) {
array[i] = this[i%this.length];
}
return array;
}
// Mutable
Array.prototype.resize = function(size) {
const array = this.slice(0);
this.length = size;
for(let i = 0; i < size; i++) {
this[i] = array[i%array.length];
}
}
Are those ok? or you think that putting it on the chain is not a good idea, if so why?

You can use modular arithmetic to loop through up to the length of your final array and then use the index to basically loop through and push that onto a new array
Using the current array value % array.length will get you the current position of the array by progressing it in a circular motion
let num = 7;
let array = [1,2,3];
let result = [];
for(let i = 0; i < num; i++){
result.push(array[i%array.length]);
}
console.log(result)

A simple while loop would suffice:
function repeat(arr, toLength) {
let output = [...arr];
while (output.length < toLength) output = [...output, ...arr];
return output.slice(0, toLength);
}
console.log(repeat([1, 2, 3], 7));
console.log(repeat([1, 2, 3], 2));

How about this version:
const nums = [1, 2, 3];
function resize(arr, length) {
let position = 0;
return Array.from(Array(length)).reduce((acc, _, i) => {
return acc.concat(arr[i % arr.length]);
}, []);
}
console.log(resize(nums, 7));

Related

Trying to sort array without sort() in JavaScript

// sorting an array
const least_num = (arr)=>{
let smallest = arr[0];
let smallest_index = 0;
for(let i=1; i<arr.length;i++){
if (arr[i] < smallest) {
smallest = arr[i];
smallest_index = i;
}
}
return smallest_index
}
const sortArray = (arr)=>{
const newArr = [];
for(let i in arr){
let smallest = least_num(arr);
console.log(smallest,i)
console.log(arr.splice(smallest,1),arr)
}
return newArr;
}
console.log(sortArray([5,4,3,2,1]));
I am trying to sort array without sort().
It stuck at array length of 2.
It may because of for loop. And how to remove element in a array using index.
A few issues:
The code never adds anything to newArr, so the function always returns an empty array. It should add the removed (spliced) element to newArr. This can be done with newArr.push(...arr.splice(smallest,1))
The for..in loop will iterate fewer times than expected, because in each iteration the array gets shorter, thereby removing future iterations for the loop. As the idea is to remove all items from the array, just keep looping until the array is empty with while (arr.length)
With these two corrections, your code works:
const least_num = (arr)=>{
let smallest = arr[0];
let smallest_index = 0;
for(let i=1; i<arr.length;i++){
if (arr[i] < smallest) {
smallest = arr[i];
smallest_index = i;
}
}
return smallest_index
}
const sortArray = (arr)=>{
const newArr = [];
while(arr.length) {
let smallest = least_num(arr);
console.log(smallest)
newArr.push(...arr.splice(smallest,1));
console.log(arr)
}
return newArr;
}
console.log(sortArray([5,4,3,2,1]));
You can also try this.
const sortArray = (arr)=>{
let originalArr = [...arr];
var sortArr = [];
while(originalArr.length) {
let val = originalArr[0];
for ( let j = 1; j < originalArr.length; j++ ) {
if(val>originalArr[j]) {
val = originalArr[j];
}
}
sortArr.push(originalArr.splice(originalArr.indexOf(val), 1)[0]);
}
return sortArr;
}
console.log(sortArray([5,4,3,2,1]));

Insert value multiple times into array based on argument passed

I have a array like this:
var oldArr = [2,3,4,2,3,5,6,4,2,3,2];
var newArr = [];
I am passing a argument(number) to a function which should insert values from oldArr into newArr taking the argument as length for each element found in old array.
function getNumbers(num){
console.log('value passed is ', num);
for(var i=0; i<arr.length;i++){
newArr.push(arr[i]);
}
console.log('newArr', newArr);
}
getNumbers(2);
For example,
if I pass number 2 as in getNumbers(2);
new array output should be:
[2,2,3,3,4,4,5,5,6,6] //as the argument/length passed is 2.
if I pass number 3 as in getNumbers(3);
[2,2,2,3,3,3,4,4,4,5,5,5,6,6,6] //as the argument/length passed is 3.
How do I achieve this?
Try this
var oldArr = [2,3,4,2,3,5,6,4,2,3,2];
function getNumbers(arr, num){
return Array.from(new Set(arr))
.map((e) => new Array(num).fill().map(v => e))
.reduce((a, b) => a.concat(b),[]);
}
console.log(getNumbers(oldArr, 2));
console.log(getNumbers(oldArr, 3));
First of all, you need to get the unique values from the array. That's the Array.from(new Set(arr));.
Secondly, we can allocate new array for each number (to be able to nicely flatten it later). That's what new Array(num).fill().map(v => e)) does. Result of this will be like [[2,2],[3,3],[4,4]..] etc.
And lastly, flatten it all using Array.prototype.reduce.
var oldArr = [2,3,4,2,3,5,6,4,2,3,2];
var uniqueArr = oldArr.filter(function(elem, index, self) {
return index == self.indexOf(elem);
})
console.log(uniqueArr)
function getNumbers(num){
var newArr = [];
for(var i=0; i<uniqueArr.length;i++){
for(var j=0;j<num;j++)
newArr.push(uniqueArr[i]);
}
console.log('newArr', newArr);
}
getNumbers(2);
getNumbers(3);
Remove all your duplicates from your old array using Array#Filter , then loop through all element and store it in new array.
The following function should work
function duplicateN(oldArray, newArray, N) {
for (var i = 0; i < oldArray.length; i++) {
for (var j = 0; j < N; j++) {
newArray.push(oldArray[i]);
}
}
}
It simply iterates over each value in the original array and then inserts it N times.
I'm not sure the usage of this, but if newArray is always empty, something like this would be more maintainable
function duplicateN(inputArray, N) {
var duplicatedArray = [];
for (var i = 0; i < inputArray.length; i++) {
for (var j = 0; j < N; j++) {
duplicatedArray.push(inputArray[i]);
}
}
return duplicatedArray;
}
var arr = [2,3,4,5];
function getNumbers(num){
var j = 1;
var newArr = [];
for(var i=0; i<arr.length;i++)
{
j = 1;
while(j<=num){
newArr.push(arr[i]);
j++;
}
}
console.log(newArr.join());
}
getNumbers(4);
let multiply_array = (arr, mi = 1) =>
[].concat.apply([], arr.filter((i, ind) =>
arr.indexOf(i) == ind).map(i =>
Array(mi).fill(i)));
The multiply_array function takes two parameters, an array and the multiplying integer. It filters through the array and finds all unique values by comparing position. It then maps over all the remaining unique integers and replaces them with an array that is the length specified by the passed in multiplying integer, and filled with the unique value. All of it is concatenated together to form one array.
var oldArr = [2, 3, 4, 2, 3, 5, 6, 4, 2, 3, 2];
var newArr = [];
let multiply_array = (arr, mi = 1) =>
[].concat.apply([], arr.filter((i, ind) =>
arr.indexOf(i) == ind).map(i =>
Array(mi).fill(i)));
console.log(multiply_array(oldArr, 3));
You can do this using chain of Array.prototype methods:
var oldArr = [2,3,4,2,3,5,6,4,2,3,2];
function getNumbers(num){
return oldArr
.filter((elem, index, arr) => !arr.slice(index + 1).includes(elem))
.sort((prev, next) => next < prev)
.reduce((result, elem) => result.concat(Array(num).fill(elem)), [])
}
console.log(getNumbers(2));
console.log(getNumbers(3));

Get elements that has no double value in an array

I have a question . How do you retrieve elements that has no double value in an array?? For example: [1,1,2,2,3,4,4,5] then you retrieve [3,5] only.
Thanks in advance
for (var j = 0; j < newArr.length; j++) {
if ((arr1.indexOf(newArr[j]) === 0) && (arr2.indexOf(newArr[j]) === 0)) {
index = newArr.indexOf(j); newArr.splice(index, 1);
}
}
If the item in the array is unique then the index found from the beginning should equal the index found from the end, in other words:
var xs = [1, 1, 2, 2, 3, 4, 4, 5];
var result = xs.filter(function(x) {
return xs.indexOf(x) === xs.lastIndexOf(x);
});
console.log(result); //=> [3, 5]
sorry for the presentation its my first post !
You have to compare each element of your array to the others in order to get the number of occurence of each element
var tab = [1,1,2,2,3,4,4,5] //The array to analyze
tab = tab.sort(); // we sort the array
show(tab); // we display the array to the console (F12 to open it)
var uniqueElementTab = []; // this array will contain all single occurence
var sameElementCounter = 0;
for(x=0;x<tab.length;x++){ // for all element in the array
sameElementCounter = 0;
for(y=0;y<tab.length;y++){ // we compare it to the others
if((tab[x]==tab[y])){
sameElementCounter+=1; // +1 each time we meet the element elsewhere
}
}
if(sameElementCounter<=1){
uniqueElementTab.push(tab[x]); //if the element is unique we add it to a new array
}
}
show(uniqueElementTab); // display result
function show(tab) { // Simple function to display the content of an array
var st="";
for(i=0;i<tab.length;i++){
st += tab[i]+" ";
}
console.log(st+"\n");
}
Hope it helps.
Here is a simple "tricky" solution using Array.sort, Array.join, Array.map, String.replace and String.split functions:
var arr = [1, 1, 2, 2, 3, 4, 4, 5];
arr.sort();
var unique = arr.join("").replace(/(\d)\1+/g, "").split("").map(Number);
console.log(unique); // [3, 5]
create new array tmp,and check already value exist by indexOf .If existed delete by splice function..
var arr = [1,1,2,2,3,4,4,5];
var tmp = [];
var dup = [];
for(var i = 0; i < arr.length; i++){
var ind = tmp.indexOf(arr[i]);
if(ind == -1){
if(dup.indexOf(arr[i]) == -1){
tmp.push(arr[i]);
}
}
else{
tmp.splice(ind,1);
dup.push(arr[i]);
}
}
console.log(tmp);
This would be my way of doing this job.
var arr = [1,1,2,2,3,4,4,5],
uniques = Object.keys(arr.reduce((p,c) => (c in p ? Object.defineProperty(p, c, {enumerable : false,
writable : true,
configurable : true})
: p[c] = c,
p), {}));
console.log(uniques);
A solution for unsorted arrays with a hash table for the items. Complexity O(2n)
var array = [1, 1, 2, 2, 3, 4, 4, 5, 1],
hash = Object.create(null),
single;
array.forEach(function (a, i) {
hash[a] = a in hash ? -1 : i;
});
single = array.filter(function (a, i) {
return hash[a] === i;
});
console.log(single);
If the array is sorted, you can solve this in O(n) (see "pushUniqueSinglePass" below):
function pushUniqueSinglePass(array, unique) {
var prev; // last element seen
var run = 0; // number of times it has been seen
for (var i = 0; i < array.length; i++) {
if (array[i] != prev) {
if (run == 1) {
unique.push(prev); // "prev" appears only once
}
prev = array[i];
run = 1;
} else {
run++;
}
}
}
function pushUniqueWithSet(array, unique) {
var set = new Set();
for (var i = 0; i < array.length; i++) {
set.add(array[i]);
}
for (let e of set) {
unique.push(set);
}
}
// Utility and test functions
function randomSortedArray(n, max) {
var array = [];
for (var i = 0; i < n; i++) {
array.push(Math.floor(max * Math.random()));
}
return array.sort();
}
function runtest(i) {
var array = randomSortedArray(i, i / 2);
var r1 = [],
r2 = [];
console.log("Size: " + i);
console.log("Single-pass: " + time(
pushUniqueSinglePass, array, r1));
console.log("With set: " + time(
pushUniqueWithSet, array, r2));
// missing - assert r1 == r2
}
[10, 100, 1000, 10000,
100000, 1000000
].forEach(runtest);
function time(fun, array, unique) {
var start = new Date().getTime();
fun(array, unique);
return new Date().getTime() - start;
}
This is much more efficient than using maps or sorting (time it!). In my machine, a 1M sorted array can have its unique elements found in 18 ms; while the version that uses a set requires 10x more.

Reversing certain number of elements in an array javascript

I am working on a code where I need to reverse certain no of elements in an array and rest should remain same. For example is an array has values of 1,2,3,4,5,6 and I have to reverse 4 elements of it then output should be 4,3,2,1,5,6. I am using below code to achieve this but getting error, please suggest.
function reverseArray(n, a) {
var interimArray1 = [];
//var interimArray2=[];
//var finalArray=[];
for (var i < n; i >= 0; i--) {
interimArray1.push[a[i]];
}
for (var i = n; i < a.length; i++) {
interimArray1.push[a[i]];
}
for (var i = 0; i < interimArray1.length; i++) {
console.log(interimArray1[i]);
}
}
var arr = [1, 2, 3, 4, 5, 6];
var num = 4;
reverseArray(num, arr);
The error in your code is that you intend to call the push method on a[i] like so:
interimArray1.push(a[i]);
but instead you write:
interimArray1.push[a[i]];
You make that mistake twice. To give arguments to the push method, you must use round parenthesis ().
With that fixed, you will see that your code works perfectly.
You can use Array#slice, Array#splice as follow.
function partialReverse(arr, num, from = 0) {
var slicedArr = arr.slice(from, num + from);
arr.splice(from, num); // Remove `num` items from array
arr.splice(from, 0, ...slicedArr.reverse()); // Add `num` reversed items
return arr;
}
var arr = [1, 2, 3, 4, 5, 6];
console.log(partialReverse(arr, 4, 0)); // Reverse four items from `arr` starting from 0th index
console.log(partialReverse(arr, 4, 1)); // Reverse four items from `arr` starting from 1st index
Lots of hints but you seem to be missing them. ;-)
You need to assign an initial value to i, so:
for (var i = n; ... )
===========^
Also, you need to use () to call functions, not [], so:
interimArray1.push(a[i]);
==================^====^
Same in the following for block. Otherwise, the code works though it's more verbose than it needs to be.
This is working :
I'm sure there are faster ways of doing it. Also, it will only work for elements at the beginning of the array but you can adjust the function for what you want to achieve.
var reverseArray = function(arr,elementsToReverse) {
var tempArrayRev = [];
var tempArray = [];
for (var i=0;i<arr.length;i++) {
if (i < elementsToReverse) {
tempArrayRev[i] = arr[i];
} else {
tempArray.push(arr[i]);
}
}
return tempArrayRev.reverse().concat(tempArray);
}
var array = [1,2,3,4,5,6];
document.getElementById('arrayOutput').innerHTML += reverseArray(array,4);
<div id="arrayOutput">Array :<br></div>
This is the answer you can test it.
function reverseArray(n, a) {
var interimArray1 = [];
for (var i = 0; i < a.length; i++) {
interimArray1.push(a[i]);
}
for (var i = num; i >=0; i--) {
interimArray1[i-1] = a[n - i];
}
for (var i = 0; i < interimArray1.length; i++) {
console.log(interimArray1[i]);
}
}
var arr = [1, 2, 3, 4, 5, 6];
var num = 4;
reverseArray(num, arr);
You could use something like this.
function reverseArray(n, arrIn) {
// Splice splits the array in 2 starting at 0 index going n long
var arrOut = arrIn.splice(0,n);
// reverse is pretty straight forward
arrOut = arrOut.reverse();
// Concat joins the two together
return arrOut.concat(arrIn);
}

JavaScript - Generating combinations from n arrays with m elements [duplicate]

This question already has answers here:
Cartesian product of multiple arrays in JavaScript
(35 answers)
Closed 1 year ago.
I'm having trouble coming up with code to generate combinations from n number of arrays with m number of elements in them, in JavaScript. I've seen similar questions about this for other languages, but the answers incorporate syntactic or library magic that I'm unsure how to translate.
Consider this data:
[[0,1], [0,1,2,3], [0,1,2]]
3 arrays, with a different number of elements in them. What I want to do is get all combinations by combining an item from each array.
For example:
0,0,0 // item 0 from array 0, item 0 from array 1, item 0 from array 2
0,0,1
0,0,2
0,1,0
0,1,1
0,1,2
0,2,0
0,2,1
0,2,2
And so on.
If the number of arrays were fixed, it would be easy to make a hard coded implementation. But the number of arrays may vary:
[[0,1], [0,1]]
[[0,1,3,4], [0,1], [0], [0,1]]
Any help would be much appreciated.
Here is a quite simple and short one using a recursive helper function:
function cartesian(...args) {
var r = [], max = args.length-1;
function helper(arr, i) {
for (var j=0, l=args[i].length; j<l; j++) {
var a = arr.slice(0); // clone arr
a.push(args[i][j]);
if (i==max)
r.push(a);
else
helper(a, i+1);
}
}
helper([], 0);
return r;
}
Usage:
cartesian([0,1], [0,1,2,3], [0,1,2]);
To make the function take an array of arrays, just change the signature to function cartesian(args) instead of using rest parameter syntax.
I suggest a simple recursive generator function:
// JS
function* cartesianIterator(head, ...tail) {
const remainder = tail.length ? cartesianIterator(...tail) : [[]];
for (let r of remainder) for (let h of head) yield [h, ...r];
}
// get values:
const cartesian = items => [...cartesianIterator(items)];
console.log(cartesian(input));
// TS
function* cartesianIterator<T>(items: T[][]): Generator<T[]> {
const remainder = items.length > 1 ? cartesianIterator(items.slice(1)) : [[]];
for (let r of remainder) for (let h of items.at(0)!) yield [h, ...r];
}
// get values:
const cartesian = <T>(items: T[][]) => [...cartesianIterator(items)];
console.log(cartesian(input));
You could take an iterative approach by building sub arrays.
var parts = [[0, 1], [0, 1, 2, 3], [0, 1, 2]],
result = parts.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));
console.log(result.map(a => a.join(', ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
After doing a little research I discovered a previous related question:
Finding All Combinations of JavaScript array values
I've adapted some of the code from there so that it returns an array of arrays containing all of the permutations:
function(arraysToCombine) {
var divisors = [];
for (var i = arraysToCombine.length - 1; i >= 0; i--) {
divisors[i] = divisors[i + 1] ? divisors[i + 1] * arraysToCombine[i + 1].length : 1;
}
function getPermutation(n, arraysToCombine) {
var result = [],
curArray;
for (var i = 0; i < arraysToCombine.length; i++) {
curArray = arraysToCombine[i];
result.push(curArray[Math.floor(n / divisors[i]) % curArray.length]);
}
return result;
}
var numPerms = arraysToCombine[0].length;
for(var i = 1; i < arraysToCombine.length; i++) {
numPerms *= arraysToCombine[i].length;
}
var combinations = [];
for(var i = 0; i < numPerms; i++) {
combinations.push(getPermutation(i, arraysToCombine));
}
return combinations;
}
I've put a working copy at http://jsfiddle.net/7EakX/ that takes the array you gave earlier ([[0,1], [0,1,2,3], [0,1,2]]) and outputs the result to the browser console.
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
console.log(charSet.reduce((a,b)=>a.flatMap(x=>b.map(y=>x+y)),['']))
Just for fun, here's a more functional variant of the solution in my first answer:
function cartesian() {
var r = [], args = Array.from(arguments);
args.reduceRight(function(cont, factor, i) {
return function(arr) {
for (var j=0, l=factor.length; j<l; j++) {
var a = arr.slice(); // clone arr
a[i] = factor[j];
cont(a);
}
};
}, Array.prototype.push.bind(r))(new Array(args.length));
return r;
}
Alternative, for full speed we can dynamically compile our own loops:
function cartesian() {
return (cartesian.cache[arguments.length] || cartesian.compile(arguments.length)).apply(null, arguments);
}
cartesian.cache = [];
cartesian.compile = function compile(n) {
var args = [],
indent = "",
up = "",
down = "";
for (var i=0; i<n; i++) {
var arr = "$"+String.fromCharCode(97+i),
ind = String.fromCharCode(105+i);
args.push(arr);
up += indent+"for (var "+ind+"=0, l"+arr+"="+arr+".length; "+ind+"<l"+arr+"; "+ind+"++) {\n";
down = indent+"}\n"+down;
indent += " ";
up += indent+"arr["+i+"] = "+arr+"["+ind+"];\n";
}
var body = "var res=[],\n arr=[];\n"+up+indent+"res.push(arr.slice());\n"+down+"return res;";
return cartesian.cache[n] = new Function(args, body);
}
var f = function(arr){
if(typeof arr !== 'object'){
return false;
}
arr = arr.filter(function(elem){ return (elem !== null); }); // remove empty elements - make sure length is correct
var len = arr.length;
var nextPerm = function(){ // increase the counter(s)
var i = 0;
while(i < len)
{
arr[i].counter++;
if(arr[i].counter >= arr[i].length){
arr[i].counter = 0;
i++;
}else{
return false;
}
}
return true;
};
var getPerm = function(){ // get the current permutation
var perm_arr = [];
for(var i = 0; i < len; i++)
{
perm_arr.push(arr[i][arr[i].counter]);
}
return perm_arr;
};
var new_arr = [];
for(var i = 0; i < len; i++) // set up a counter property inside the arrays
{
arr[i].counter = 0;
}
while(true)
{
new_arr.push(getPerm()); // add current permutation to the new array
if(nextPerm() === true){ // get next permutation, if returns true, we got them all
break;
}
}
return new_arr;
};
Here's another way of doing it. I treat the indices of all of the arrays like a number whose digits are all different bases (like time and dates), using the length of the array as the radix.
So, using your first set of data, the first digit is base 2, the second is base 4, and the third is base 3. The counter starts 000, then goes 001, 002, then 010. The digits correspond to indices in the arrays, and since order is preserved, this is no problem.
I have a fiddle with it working here: http://jsfiddle.net/Rykus0/DS9Ea/1/
and here is the code:
// Arbitrary base x number class
var BaseX = function(initRadix){
this.radix = initRadix ? initRadix : 1;
this.value = 0;
this.increment = function(){
return( (this.value = (this.value + 1) % this.radix) === 0);
}
}
function combinations(input){
var output = [], // Array containing the resulting combinations
counters = [], // Array of counters corresponding to our input arrays
remainder = false, // Did adding one cause the previous digit to rollover?
temp; // Holds one combination to be pushed into the output array
// Initialize the counters
for( var i = input.length-1; i >= 0; i-- ){
counters.unshift(new BaseX(input[i].length));
}
// Get all possible combinations
// Loop through until the first counter rolls over
while( !remainder ){
temp = []; // Reset the temporary value collection array
remainder = true; // Always increment the last array counter
// Process each of the arrays
for( i = input.length-1; i >= 0; i-- ){
temp.unshift(input[i][counters[i].value]); // Add this array's value to the result
// If the counter to the right rolled over, increment this one.
if( remainder ){
remainder = counters[i].increment();
}
}
output.push(temp); // Collect the results.
}
return output;
}
// Input is an array of arrays
console.log(combinations([[0,1], [0,1,2,3], [0,1,2]]));
You can use a recursive function to get all combinations
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
let loopOver = (arr, str = '', final = []) => {
if (arr.length > 1) {
arr[0].forEach(v => loopOver(arr.slice(1), str + v, final))
} else {
arr[0].forEach(v => final.push(str + v))
}
return final
}
console.log(loopOver(charSet))
This code can still be shorten using ternary but i prefer the first version for readability 😊
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
let loopOver = (arr, str = '') => arr[0].map(v => arr.length > 1 ? loopOver(arr.slice(1), str + v) : str + v).flat()
console.log(loopOver(charSet))
Another implementation with ES6 recursive style
Array.prototype.cartesian = function(a,...as){
return a ? this.reduce((p,c) => (p.push(...a.cartesian(...as).map(e => as.length ? [c,...e] : [c,e])),p),[])
: this;
};
console.log(JSON.stringify([0,1].cartesian([0,1,2,3], [[0],[1],[2]])));

Categories