How to merge two different arrays in Javascript? - javascript

I have this array,
var arr1 = [19, 1, 1, 1, 1];
and another array,
var arr2 = ["Default", "Dynamic", "Assessment", "Risk", "Privacy"];
What I would like is to merge them somehow such that it would look something like this,
var merged_array = [ ["Default", 19], ["Dynamic", 1], ["Assessment", 1], ["Risk", 3], ["Privacy", 2] ];
how would I do that? I tried join but I did not achieve what I wanted. Thanks in advance!

Using a for loop:
var merged_array = new Array(arr1.length);
for (var i = 0; i < arr1.length; i++) {
merged_array[i] = new Array(arr2[i], arr1[i]);
}
This assumes arr1 and arr2 have the same length.

If you have jquery or equivalent:
var merged_array = $.map(arr1, function(e, i) {
return [arr2[i], e];
});
If not, then just use a for loop, same idea.
var merged_array = []
for (var i = 0; i < arr1.length && i < arr2.length; i++) {
merged_array[i] = [arr2[i], arr1[i]];
}

var result = new Array();
for (var i=0; i<arr1 .length && i<arr2.length ; i++) {
result[i] = new Array();
result[i][0] = arr1[i];
result[i][1] = arr2[i];
}

I'd probably extend the array object especially if this is a common task. Something like this:
Array.prototype.myMerge = function(arr){
var returnArr = [];
for(var i = 0, len = this.length; i < len; i++){
returnArr[i] = [this[i], arr[i]];
}
return returnArr;
};
then you could call it like this:
var merged_array = arr1.myMerge(arr2)
Of course you'd have to add some error checking on the length of the arrays, this function assumes that arr1 is longer or the same length as arr2. But that depends on what you want to do if arr1 and arr2 are different lengths, your question seems to assume they are the same length.

If you include the library underscore.js (prototype.js also has something similar), you can use _.zip(array1,array2). They provide example usage with 3 arrays.
From http://underscorejs.org/#zip :
zip_.zip(*arrays)
Merges together the values of each of the arrays with the values at the corresponding position. Useful when you have separate data sources that are coordinated through matching array indexes. If you're working with a matrix of nested arrays, zip.apply can transpose the matrix in a similar fashion.
_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
=> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]]

Related

Checking whether certain item is in certain array using javascript

I have 10 different arrays. Each array has different numbers.
array1 = [1,2,3,4,5]
array2 = [6,7,8,9,10]
...
array 10 = [51,52,53,54]
let's say I pass in 7. Then I want to know which array it is from and want to return array number. So in this case it is going to be 2.
Should I write a switch statement for each array? Appreciate it in javascript.
try:
var arrays = [array1, array2, ..., array10];
for(var i=0; i<arrays.length; ++i) {
if (arrays[i].indexOf(value) != -1) {
console.log('found in array' + (i+1));
}
}
You cannot directly retrieve the name of array.The reason is this variable is only storing a reference to the object.
Instead you can have a key inside the same array which represent its name. Then indexOf can be used to find the array which contain the number , & if it is so, then get the array name
var array1 = [1,2,3,4,5];
array1.name ="array1";
var array2 = [6,7,8,9,10];
array2.name ="array2";
var array10 = [51,52,53,54]
array10.name ="array10";
var parArray = [array1,array2,array10]
function _getArrayName(number){
for(var o=0;o<parArray.length;o++){
var _tem = parArray[o];
if(parArray[o].indexOf(number) !==-1){
console.log(parArray[o].name);
}
}
}
_getArrayName(6) //prints array2
jsfiddle
One fast method should be using hash tables or as i would like to call LUT. Accordingly this job boils down to a single liner as follows;
var arrs = {
arr1 : [1,2,3,4,5],
arr2 : [6,7,8,9,10],
arr3 : [12,14,16,17],
arr4 : [21,23,24,25,27,20],
arr5 : [31,34,35,39],
arr6 : [45,46,44],
arr7 : [58,59],
arr8 : [66,67,69,61],
arr9 : [72,73,75,79,71],
arr0 : [81,85,98,99,90,80]
},
lut = Object.keys(arrs).reduce((p,c) => {arrs[c].forEach(n => p[n]=c); return p},{}),
findar = n => lut[n];
document.write("<pre>" + findar(12) + "</pre>");
One way to do this is have the arrays in an object and iterate over the keys/values. This method doesn't presume the arrays (and therefore their names) are in sequential order.
Note: this will always return a the first match from the function and terminate the search.
var obj = {
array1: [1, 2, 3, 4, 5],
array2: [6, 7, 8, 9, 10],
array3: [51, 52, 53, 54],
array4: [51, 52, 53, 54, 7]
}
function finder(obj, test) {
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (obj[key].indexOf(test) > -1) {
return key.match(/\d+/)[0];
}
}
return false;
}
finder(obj, 7); // '2'
DEMO
If you want to find all instances of a value in all arrays the function needs to be altered slightly.
function finder(obj, test) {
var keys = Object.keys(obj);
var out = [];
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (obj[key].indexOf(test) > -1) {
out.push(key.match(/\d+/)[0]);
}
}
return out;
}
finder(obj, 7); // ['2', '4']
DEMO

Sort Object Containing Multiple Arrays: JavaScript [duplicate]

for hours i've been trying to figure out how to sort 2 array dependently.
Let's say I have 2 arrays.
First one:
array1 = ['zzzzz', 'aaaaaa', 'ccccc'];
and the second one:
array2 = [3, 7, 1];
I sort the first one with array1.sort(); and it becomes [aaaaaa, cccccc, zzzzzz]
now what I want is that the second one becomes [7, 1, 3]
I think it's quite simple but i'm trying to implement this in something a little more complex, im new and i keep mixing up things.
Thanks
I would "zip" them into one array of objects, then sort that with a custom sort callback, then "unzip" them back into the two arrays you wanted:
var array1 = ['zzzzz', 'aaaaaa', 'ccccc'],
array2 = [3, 7, 1],
zipped = [],
i;
for(i=0; i<array1.length; ++i) {
zipped.push({
array1elem: array1[i],
array2elem: array2[i]
});
}
zipped.sort(function(left, right) {
var leftArray1elem = left.array1elem,
rightArray1elem = right.array1elem;
return leftArray1elem === rightArray1elem ? 0 : (leftArray1elem < rightArray1elem ? -1 : 1);
});
array1 = [];
array2 = [];
for(i=0; i<zipped.length; ++i) {
array1.push(zipped[i].array1elem);
array2.push(zipped[i].array2elem);
}
alert('Sorted arrays:\n\narray1: ' + array1 + '\n\narray2: ' + array2);
Here's a working fiddle.
Here's a simple function that will do the trick:
function sortTogether(array1, array2) {
var merged = [];
for(var i=0; i<array1.length; i++) { merged.push({'a1': array1[i], 'a2': array2[i]}); }
merged.sort(function(o1, o2) { return ((o1.a1 < o2.a1) ? -1 : ((o1.a1 == o2.a1) ? 0 : 1)); });
for(var i=0; i<merged.length; i++) { array1[i] = merged[i].a1; array2[i] = merged[i].a2; }
}
Usage demo (fiddle here):
var array1 = ['zzzzz', 'aaaaaa', 'ccccc'];
var array2 = [3, 7, 1];
console.log('Before..: ',array1,array2);
sortTogether(array1, array2); // simply call the function
console.log('After...: ',array1,array2);
Output:
Before..: ["zzzzz", "aaaaaa", "ccccc"] [3, 7, 1]
After...: ["aaaaaa", "ccccc", "zzzzz"] [7, 1, 3]
Instead of two arrays of primitive types (strings, numbers) you can make an array of objects where one property of the object is string (containing "aaaaa", "cccccc", "zzzzzz") and another is number (7,1,3). This way you will have one array only, which you can sort by any property and the other property will remain in sync.
It just so happens I had some old code lying around that might do the trick:
function arrVirtualSortGetIndices(array,fnCompare){
var index=array.map(function(e,i,a){return i;});
fnCompare=fnCompare || defaultStringCompare;
var idxCompare=function (aa,bb){return fnCompare(array[aa],array[bb]);};
index.sort(idxCompare);
return index;
function defaultStringCompare(aa,bb){
if(aa<bb)return -1;
if(bb<aa)return 1;
return 0;
}
function defaultNumericalCompare(aa,bb){
return aa-bb;
}
}
function arrReorderByIndices(array,indices){
return array.map(
function(el,ix,ar){
return ar[indices[ix]];
}
);
}
var array1 = ['zzzzz', 'aaaaaa', 'ccccc'];
var array2 = [3, 7, 1];
var indices=arrVirtualSortGetIndices(array1);
var array2sorted=arrReorderByIndices(array2,indices);
array2sorted;
/*
7,1,3
*/
Sorry, I don't do 'fors'. At least not when I don't have to.
And fiddle.
Also, an alternative fiddle that sorts the results when given an array of objects like this:
given:
var list = [
{str:'zzzzz',value:3},
{str:'aaaaa',value:7},
{str:'ccccc',value:1}
];
outputs:
[
{str: "aaaaa", value: 7},
{str: "ccccc", value: 1},
{str: "zzzzz", value: 3}
]
Assumption:
The arrays are the same length (this is implied by your question)
the contents can be compared with > and < (true in your example, but I wanted to make it clear that it was assumed here)
So then we can use an insertion sort.
var value,len = array1.length;
for (i=0; i < len; i++) {
value = array1[i];
for (j=i-1; j > -1 && array1[j] > value; j--) {
array1[j+1] = array1[j];
array2[j+1] = array2[j];
}
items[j+1] = value;
}
Using a solution found here to find the new indices after sorting an array, you can apply those indices to array2 like so.
function sortWithIndices(toSort) {
for (var i = 0; i < toSort.length; i++) {
toSort[i] = [toSort[i], i];
}
toSort.sort(function(left, right) {
return left[0] < right[0] ? -1 : 1;
});
toSort.sortIndices = [];
for (var j = 0; j < toSort.length; j++) {
toSort.sortIndices.push(toSort[j][2]);
toSort[j] = toSort[j][0];
}
return toSort;
}
var array1 = ['zzzz', 'aaaa', 'cccc'];
var array2 = [3, 7, 1];
// calculate the indices of array1 after sorting. (attached to array1.sortIndices)
sortWithIndices(array1);
// the final array after applying the sorted indices from array1 to array2
var final = [];
// apply sorted indices to array2
for(var i = 0; i < array1.sortIndices.length; i++)
final[i] = array2[array1.sortIndices[i]];
// output results
alert(final.join(","));
JSFiddle Demo

Concisely mapping 2 columns from 2D array to key:value pairs

In this example snippet of code, I selectively convert 2 columns from my 2D array into an object. The 1st column represents the keys, the 2nd represents the values.
I feel like there is a more concise way of codifying this idea without so many lines of code.
var my2dArray = [ ['a',2], ['b',3], ['c',4] ];
var keys = [];
var values = [];
var myObj = {};
for(var row = 1; row < my2dArray.length; row++) {
keys[row] = my2dArray[row][0];
values[row] = my2dArray[row][1];
myObj[keys[row]] = values[row];
}
console.log(prod_compare); // outputs object
In reality, I have a 4 column array. Don't mind the simplicity of my2dArray. Is there a way to select these two columns for mapping to an object without having to declare 2 temporary arrays?
Your code is fundamentally OK, but it can be more concise without being obfuscated:
var my2dArray = [ ['a',2], ['b',3], ['c',4] ];
var myObj = {};
for (var i=0, iLen=my2dArray.length; i<iLen; i++) {
myObj[my2dArray[i][0]] = my2dArray[i][1];
}
This may convert [['a', 1, 2, 3], ['b', 1, 2, 3]] to {a: [1, 2, 3], b: [1, 2, 3]}.
for(var row = 0; row < my2dArray.length; row++) {
keys[row] = my2dArray[row][0];
values[row] = my2dArray[row].slice(1);
myObj[keys[row]] = values[row];
}

How to join two arrays into one two-dimensional array?

I have two arrays. How can I join them into one multidimensional array?
The first array is:
var arrayA = ['Jhon, kend, 12, 62626262662',
'Lisa, Ann, 43, 672536452',
'Sophie, Lynn, 23, 636366363'];
My other array has the values:
var arrayB = ['Jhon', 'Lisa', 'Sophie'];
How could I get an array with this format??
var jarray = [['Jhon', ['Jhon, kend, 12, 62626262662']],
['Lisa', ['Lisa, Ann, 43, 672536452']],
['Sohphie', ['Sophie, Lynn, 23, 636366363']]]
var jarray = [];
for (var i=0; i<arrayA.length && i<arrayB.length; i++)
jarray[i] = [arrayB[i], [arrayA[i]]];
However, I wouldn't call that "multidimensional array" - that usually refers to arrays that include items of the same type. Also I'm not sure why you want the second part of your arrays be an one-element array.
Here is a map version
const arrayA = ['Jhon, kend, 12, 62626262662',
'Lisa, Ann, 43, 672536452',
'Sophie, Lynn, 23, 636366363'];
const arrayB = ['Jhon', 'Lisa', 'Sophie'];
/* expected output
var jarray = [['Jhon', ['Jhon, kend, 12, 62626262662']],
['Lisa', ['Lisa, Ann, 43, 672536452']],
['Sohphie', ['Sophie, Lynn, 23, 636366363']]] */
const jarray = arrayB.map((item,i) => [item,[arrayA[i]]]);
console.log(jarray);
You can use Underscore.js http://underscorejs.org/#find
Looks through each value in the list, returning the first one that passes a truth test (iterator). The function returns as soon as it finds an acceptable element, and doesn't traverse the entire list.
var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
=> 2
Then, you can make the same with the array B elements and by code, make a join.
This is what I did to get what you were asking:
var jarray = [];
for (var i = 0; i < arrayB.length; i++) {
jarray[i] = [];
jarray[i].push(arrayB[i]);
var valuesList = [],
comparator = new RegExp(arrayB[i]);
for (var e = 0; e < arrayA.length; e++) {
if (comparator.test(arrayA[e])) {
valuesList.push(arrayA[e]);
}
}
jarray[i].push(valuesList);
}

making sure my array of random values doesn't contain duplicate values

I was wondering if anyone can advise how I can make sure the random array I'm generating from another array doesn't contain duplicate values, want to make sure that arr2 contains unique values?
JS
var limit = 5,
i = 0,
arr1 = [12, 14, 67, 45, 8, 45, 56, 8, 33, 89],
arr2 = [];
for ( i; i < limit; i++ ){
var rand = Math.floor((Math.random()*9)+1);
arr2.push( arr1[rand] );
}
console.log(arr2);
Maybe an if statement that compares arr1[rand] with arr2[i] ?
Create a temporary array that is a copy of arr1 containing only unique values:
// Copy unique values in arr1 into temp_arr
var temp_obj = {}, temp_arr = [], i;
for(i = arr1.length; i--;)
temp_obj[arr1[i]] = 1;
for(i in temp_obj)
temp_arr.push(i);
Then you can remove the element from temp_arr each time you add it to arr2. Since we used object keys when copying we have strings, so we can use + to convert them back to numbers when pushing into arr2:
arr2.push(+temp_arr.splice(rand, 1)[0]);
You should also change how you pick random numbers to:
var rand = Math.floor(Math.random()*temp_arr.length);
Whole code:
var limit = 5,
arr1 = [12, 14, 67, 45, 8, 45, 56, 8, 33, 89],
arr2 = [],
rand,
temp_obj = {},
temp_arr = []
i;
// Copy unique values from arr1 into temp_arr
for(i = arr1.length; i--;)
temp_obj[arr1[i]] = 1;
for(i in temp_obj)
temp_arr.push(i);;
// Move elements one at a time from temp_arr to arr2 until limit is reached
for (var i = limit; i--;){
rand = Math.floor(Math.random()*temp_arr.length);
arr2.push(+temp_arr.splice(rand, 1)[0]);
}
console.log(arr2);
The naive O(n^2) solution is to simply check each element and see if any other position in the array has the same value.
A linear time solution can be achieved using a hashset data structure. You can hack one in JavaScript using objects:
var set = {};
set['0'] = true;
set['1'] = true;
if(set.hasOwnProperty('0')) {
alert("duplicate 0!");
}
If the numbers are integers and relatively small, then you can keep track of them in an array of boolean values.
See http://bost.ocks.org/mike/shuffle/ for good info on the Fischer/Yates shuffle. For your problem, you could take the first five elements of the shuffled deck.
try this
for ( i; i < limit; i++ ){
var rand = Math.floor((Math.random()*9)+1);
for(j=0; j < arr1.length; j++)
if(rand == arr1[j]
{
blnfound = true;
break;
}
if(!blnfound)
arr2.push( arr1[rand] );
}
By using jQuery.inArray function :)
var limit = 5,
arr1 = [12, 14, 67, 45, 8, 45, 56, 8, 33, 89],
l = arr1.length,
arr2 = [];
while( limit ){
var tmp = arr1[ Math.random() * l | 0 ];
// for unsigned numbers '|0' construction works like Math.floor
if( !~$.inArray( tmp, arr2 ) ) {
// if not found $.inArray returns -1 ( == ~0 ), then !~-1 == true
limit--;
arr2[ arr2.length ] = tmp;
}
}
console.log( arr2 );

Categories

Resources