create new arrays for repeating elements in javascript - javascript

I have a JavaScript array with 8 elements and some elements are repeating. I want to create separate arrays for identical elements.
example:
original array is [1,1,1,3,3,1,2,2]
resulting arrays will be [1,1,1,1],[3,3],[2,2]
I want a function similar to this:
var array=[1,1,1,3,3,1,2,2];
var createNewArrays=function(array){
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < array.length; j++) {
}
}
};

You could use a hash table as reference to the sub arrays for the collection.
var array = [1, 1, 1, 3, 3, 1, 2, 2],
result = [];
array.forEach(function (a) {
a in this || result.push(this[a] = []);
this[a].push(a);
}, Object.create(null));
console.log(result);

var arr = [1,1,1,3,3,1,2,2];
var hash = Object.create(null);
var result = arr.reduce(function(r, n) {
if(!hash[n]) {
hash[n] = [];
r.push(hash[n]);
}
hash[n].push(n);
return r;
}, []);
console.log(result);
And an ES6 solution that uses Map, and spread:
const arr = [1,1,1,3,3,1,2,2];
const result = [...arr.reduce((r, n) =>
r.set(n, (r.get(n) || []).concat(n)),
new Map()).values()];
console.log(result);

Let's assume you want the resulting arrays to be properties on an object keyed by the value they represent. You just loop through the array, creating or adding to the arrays on the object properties as you go:
var array=[1,1,1,3,3,1,2,2];
var result = {};
array.forEach(function(entry) {
(result[entry] = result[entry] || []).push(entry);
});
console.log(result);
That's a bit dense, here's a clearer version:
var array=[1,1,1,3,3,1,2,2];
var result = {};
array.forEach(function(entry) {
var subarray = result[entry];
if (!subarray) {
subarray = result[entry] = [];
}
subarray.push(entry);
});
console.log(result);

Related

Replicate array to certain length in 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));

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));

Pull values out of an array and into another array in a different order with JavaScript

I have an array like this:
var products = [
['date1','prod1',1,2],
['date2','prod2',3,4],
['date3','prod3',5,6],
['date4','prod4',7,8],
['date5','prod5',9,0]
];
And need to pull the integers out of the array and format it like this:
var newProductsArray = [[1,3,5,7,9],[2,4,6,8,0]];
It needs to be able to be dynamic and expand because the products array will have more "columns".
I have this code but it's doing it backwards and can't figure out how to loop through and just break up the arrays. I am sure it's something simple I'm missing.
var metricStartPosition = 2;
var dataSetInnerArray = [];
var dataSetArray = [];
for (var i = 0; i < array.length; i++) {
for (var k = metricStartPosition; k < array[i].length; k++) {
dataSetInnerArray.push(array[i][k]);
};
dataSetArray.push(dataSetInnerArray);
dataSetInnerArray = [];
};
You can do something like this:
var products = [
['date1','prod1',1,2,'a','b'],
['date2','prod2',3,4,'c','d'],
['date3','prod3',5,6,'e','f'],
['date4','prod4',7,8,'g','h'],
['date5','prod5',9,0,'i','j']
];
var metricStartPosition = 2;
var newProductsArray = products.reduce(function(output, item) {
item.slice(metricStartPosition).forEach(function(v, i) {
(output[i] || (output[i] = [])).push(v);
});
return output;
}, []);
console.log(JSON.stringify(newProductsArray));
Should work with any number of columns.
Of course you could use nested .forEach() loops or old-school nested for loops instead of .forEach() inside .reduce().
If I got your question correctly, inverting the order of the two for loops will do it:
var metricStartPosition = 2;
var dataSetInnerArray = [];
var dataSetArray = [];
for (var k = metricStartPosition; k < products[0].length; k++) {
for (var i = 0; i < products.length; i++) {
dataSetInnerArray.push(products[i][k]);
};
dataSetArray.push(dataSetInnerArray);
dataSetInnerArray = [];
};
Related Post
This should flip the array.
var newArray = array[0].map(function(col, i) {
return array.map(function(row) {
return row[i]
})
});
As a function this is:
function foo (array) {
var newArray = array[0].map(function(col, i) {
return array.map(function(row) {
return row[i]
})
});
return newArray;
}
By flip the array I mean this:
1 2 3 1 4 7
4 5 6 -> 2 5 8
7 8 9 3 6 9
And in your case:
var products = [
['date1','prod1',1,2],
['date2','prod2',3,4],
['date3','prod3',5,6],
['date4','prod4',7,8],
['date5','prod5',9,0]
];
var newProducts = [
['date1','date2','date3','date4','date5'],
['prod1','prod2','prod3','prod4','prod5'],
[1,3,5,7,9],
[2,4,6,8,0]
];
You could try and index all the columns one-by-one (assuming all the rows of the data is of the same types column-wise:
arrayRow = products[0] //['date1','prod1',1,2]
newProductsArray = [];
intIndices = [];
arrayRow.forEach(function(data, i) {
if (typeof(data) === 'number')
intIndices.push(i);
});
// intIndices should be [2, 3]
and then iterate through the whole products array to get all the columns:
intIndices.forEach(function (colIndex) {
innerArray = [];
for (var i = 0; i < products.length; i++) {
innerArray.push(products[i][colIndex]);
}
newProductsArray.push(innerArray);
});
// you should get nested arrays with all the integer columns
// [ [ 1, 3, 5, 7, 9 ],
// [ 2, 4, 6, 8, 0 ] ]

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.

Trying to leave input parameters unchanged

I am trying to write a function that performs operations on an array and returns a different copy of the array and leaves the original one unchanged. I thought I could do this by declaring var array2 = array and then proceeding with the array operations. What am I doing wrong?
Here is my sample function:
var partition = function(array, p){
var pivot = array[p];
var length = array.length;
// make a copy and move pivot to the front
var array2 = array;
array2[p] = array2[0];
array2[0] = pivot;
// partition the array
var i = 1;
for (var j = 1; j < length; j++){
//console.log('i='+i+', j='+j)
if (array2[j] < pivot) {
var temp = array2[j];
array2[j] = array2[i];
array2[i] = temp;
i++;
}
}
//console.log('array after partitioning: ' + array)
// swap pivot
array2[0] = array2[i-1];
array2[i-1] = pivot;
var answer = {array: array2, p: i-1}
return answer;
};
And my sample call:
var a = [3, 2, 1];
partition(a, 0);
console.log(a); // prints [1,2,3] but I want [3,2,1]
add this line instead of array2=array because it's only create a reference to array not the new array2.
var array2 =array.slice(0); //it will create a new array not the reference.
Fiddle http://jsfiddle.net/N64w3/
var array2 = array.slice(0) or just array.slice() will clone your array
Here you have reference to that

Categories