Well my brains are melting... I am trying to accomplish the following:
I know how many arrays and how many elements each array have.
These numbers are dynamic, but lets say there's: 3 arrays with 18 elements in each.
Example:
["106","142","112","77","115","127","87","127","156","118","91","93","107","151","110","79","40","186"]
["117","139","127","108","172","113","79","128","121","104","105","117","139","109","137","109","82","137"]
["111","85","110","112","108","109","107","89","104","108","123","93","125","174","129","113","162","159"]
Now I want to get the average of element 1 of all three arrays, and element 2 of all three and so on.
The end result should be one array with the average of all 18 elements.
Something like:
var result_array = [];
for (i = 0; i < 3; i++) {
result_array.push(arrayone[i] + arraytwo[i] + arraythree[i]) / 3
}
This would work if 3 was fixed, but the amount of arrays is dynamic.
Hope this make sense...
var arrays = [
[106,142,112,77,115,127,87,127,156,118,91,93,107,151,110,79,40,186],
[117,139,127,108,172,113,79,128,121,104,105,117,139,109,137,109,82,137],
[111,85,110,112,108,109,107,89,104,108,123,93,125,174,129,113,162,159],
[104,153,110,112,108,109,107,89,104,108,123,93,125,174,129,113,162,159]
/* Can be any amount of arrays */
],
result = [];
//Rounding to nearest whole number.
for(var i = 0; i < arrays[0].length; i++){
var num = 0;
//still assuming all arrays have the same amount of numbers
for(var i2 = 0; i2 < arrays.length; i2++){
num += arrays[i2][i];
}
result.push(Math.round(num / arrays.length));
}
alert(result);
You did tag this question with underscore.js, so you can use the _.zip method. This puts all the first elements in an array together and so on. You can then average each of those arrays.
See CodePen.
var arr1 = ["106","142","112","77","115","127","87","127","156","118","91","93","107","151","110","79","40","186"]
var arr2 = ["117","139","127","108","172","113","79","128","121","104","105","117","139","109","137","109","82","137"]
var arr3 = ["111","85","110","112","108","109","107","89","104","108","123","93","125","174","129","113","162","159"]
// ... as many more arrays as you want
var avgEmAll = function (arrays) {
// zip with array of arrays https://stackoverflow.com/a/10394791/327074
return _.zip.apply(null, arrays).map(avg)
}
// average an array https://stackoverflow.com/a/10624256/327074
var avg = function (x) {
return x.reduce(function (y, z) {return Number(y) + Number(z)}) / x.length
}
console.log(avgEmAll([arr1, arr2, arr3]))
With ES6 arrow functions (CodePen):
const avgEmAll = arrays => _.zip.apply(null, arrays).map(avg)
const sum = (y, z) => Number(y) + Number(z)
const avg = x => x.reduce(sum) / x.length
Wrote this solution in Java but you can get help with logic. Hope it helps.
ArrayList<Integer> averageArrayList = new ArrayList<>();
int arrayListLength = arrayList1.length(); //assuming previous arraylists have same size.
for(int i=0; i<arrayListLength; i++){
int averageValue = (arrayList1.get(i) + arrayList2.get(i) + arrayList3.get(i)) / 3;
//adds average value to current index.
averageArrayList.add(i, averageValue);
}
//averageArrayList is ready with your values..
var result = getAvg( [ 1, 2, 3 ], [ 2, 3, 4 ] )
console.log( result ) // [ 1.5, 2.5, 3.5 ]
function getAvg() {
var a = arguments
var nar = a.length
var nel = a[ 0 ].length
var el, ar, avg, avgs = []
for( el = 0; el < nel; ++el ) {
avg = 0
for( ar = 0; ar < nar; ++ar ) avg += a[ ar ][ el ]
avgs[ el ] = avg / nar
}
return avgs
}
This function will take any number of arrays and figure out their average. It uses the + operator to automatically cast the string to a number. It is dynamic in that it doesn't care what length the arrays are, or how many there are, as long as they are all equal in length. Since we can assume that they are all the same length( based on the question ) it iterates over the length of the first array. It doesn't round because that wasn't asked for.
function average_of_arrays(...arrays) {
let result = [];
for(let array_index in arrays[0]) {
let total = 0;
for (let arr of arrays) {
total += +arr[array_index]
}
result.push(total / arrays.length);
}
return result;
}
let arr1 = ["106", "142", "112", "77", "115", "127", "87", "127", "156", "118", "91", "93", "107", "151", "110", "79", "40", "186"];
let arr2 = ["117", "139", "127", "108", "172", "113", "79", "128", "121", "104", "105", "117", "139", "109", "137", "109", "82", "137"];
let arr3 = ["111", "85", "110", "112", "108", "109", "107", "89", "104", "108", "123", "93", "125", "174", "129", "113", "162", "159"];
function average_of_arrays(...arrays) {
let result = [];
for(let array_index in arrays[0]) {
let total = 0;
for (let arr of arrays) {
total += +arr[array_index]
}
result.push(total / arrays.length);
}
return result;
}
console.log(average_of_arrays(arr1, arr2, arr3));
The answer here is to use a loop. Let's call your arrays arr1, arr2, and arr3.
var averages = [];
for(i = 0; i < arr1.length; i++) {
var a = arr1[i];
var b = arr2[i];
var c = arr3[i];
var avg = (a + b + c) / 3;
averages.push(avg);
}
For each iteration of this loop, it will:
-Assign the next digit of each array to a variable (starting at index 0)
-Find the average of the three numbers
-Add the result of the calculation to the averages array
Related
What is an elegant way to take a javascript array, order by the frequency of the values, and then filter for uniques?
So,
["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"]
becomes
["oranges, "bananas", "apples"]
Compute the frequency of each item first.
{
apples: 1,
oranges: 4,
bananas: 2
}
Then create an array from this frequency object which will also remove the duplicates.
["apples", "oranges", "bananas"]
Now sort this array in descending order using the frequency map we created earlier.
function compareFrequency(a, b) {
return frequency[b] - frequency[a];
}
array.sort(compareFrequency);
Here's the entire source (using the newly introduced Array functions in ECMA 5) and combining the de-duplication and frequency map generation steps,
function sortByFrequency(array) {
var frequency = {};
array.forEach(function(value) { frequency[value] = 0; });
var uniques = array.filter(function(value) {
return ++frequency[value] == 1;
});
return uniques.sort(function(a, b) {
return frequency[b] - frequency[a];
});
}
Same as above using the regular array iteration.
function sortByFrequencyAndRemoveDuplicates(array) {
var frequency = {}, value;
// compute frequencies of each value
for(var i = 0; i < array.length; i++) {
value = array[i];
if(value in frequency) {
frequency[value]++;
}
else {
frequency[value] = 1;
}
}
// make array from the frequency object to de-duplicate
var uniques = [];
for(value in frequency) {
uniques.push(value);
}
// sort the uniques array in descending order by frequency
function compareFrequency(a, b) {
return frequency[b] - frequency[a];
}
return uniques.sort(compareFrequency);
}
// returns most frequent to least frequent
Array.prototype.byCount= function(){
var itm, a= [], L= this.length, o= {};
for(var i= 0; i<L; i++){
itm= this[i];
if(!itm) continue;
if(o[itm]== undefined) o[itm]= 1;
else ++o[itm];
}
for(var p in o) a[a.length]= p;
return a.sort(function(a, b){
return o[b]-o[a];
});
}
//test
var A= ["apples","oranges","oranges","oranges","bananas","bananas","oranges"];
A.byCount()
/* returned value: (Array)
oranges,bananas,apples
*/
I was actually working on this at the same time - the solution I came up with is pretty much identical to Anurag's.
However I thought it might be worth sharing as I had a slightly different way of calculating the frequency of occurrences, using the ternary operator and checking if the value has been counted yet in a slightly different way.
function sortByFrequencyAndFilter(myArray)
{
var newArray = [];
var freq = {};
//Count Frequency of Occurances
var i=myArray.length-1;
for (var i;i>-1;i--)
{
var value = myArray[i];
freq[value]==null?freq[value]=1:freq[value]++;
}
//Create Array of Filtered Values
for (var value in freq)
{
newArray.push(value);
}
//Define Sort Function and Return Sorted Results
function compareFreq(a,b)
{
return freq[b]-freq[a];
}
return newArray.sort(compareFreq);
}
Basic strategy:
Create an object to use as a hash table to track the frequency of each item in the array to be sorted.
Create a new array containing the item, frequency pairs.
Sort this array on frequency in descending order.
Extract the items from that array.
Code:
function descendingUniqueSort(toBeSorted) {
var hash = new Object();
toBeSorted.forEach(function (element, index, array) {
if (hash[element] == undefined) {
hash[element] = 1;
}
else {
hash[element] +=1;
}});
var itemCounts = new Array();
for (var key in hash) {
var itemCount = new Object();
itemCount.key = key;
itemCount.count = hash[key];
itemCounts.push(itemCount);
}
itemCounts.sort(function(a,b) { if(a.count<b.count) return 1;
else if (a.count>b.count) return -1; else return 0;});
return itemCounts.map(function(itemCount) { return itemCount.key; });
}
var arr = ["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"].sort();
var freq = {};
for (var s in arr) freq[s] = freq[s] ? freq[s] + 1 : 0;
arr.sort(function(a, b) { return freq[a] > freq[b] ? -1 : 1; });
for (var i = arr.length - 1; i > 0; i--) if (arr[i] == arr[i - 1]) arr.splice(i,1);
alert(arr.join(","));
for the first step to compute
{
oranges: 4,
bananas: 2,
apples: 1
}
you can use countBy function of underscroe.js
var all=["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"];
var frequency=_.countBy(all,function(each){return each});
so frequency object will contain frequency of all unique values, and you can get an unique list by simply calling _.uniq(all), and to sort that unique list by the _.sortBy method of underscore and using your frequency object you can use
_.sortBy(_.uniq(all),function(frequencyKey){return -frequency[frequencyKey]});
-ve sign is used here to sort the list in decending order by means of frequency value as per your requirement.
You can check the the documentation of http://underscorejs.org/ for further optimization by your own trick :)
Let me put a minimal code to get unique values (and with frequencies) in ES6.
var arr = ["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"];
console.log([...new Set(arr)])
It is also applied to array of objects to aggregate some properties.
var arr = [{"fruit":"apples"}, {"fruit":"oranges"}, {"fruit":"oranges"}, {"fruit":"oranges"}, {"fruit":"bananas"}, {"fruit":"bananas"}, {"fruit":"oranges"}];
console.log(arr.reduce((x,y)=>{if(x[y.fruit]) {x[y.fruit]++;return x;} else {var z={};z[y.fruit]=1;return Object.assign(x,z);}},{}))
Create a counter of the array's elements using reduce:
arr.reduce(
(counter, key) => {counter[key] = 1 + counter[key] || 1; return counter},
{}
);
Sort the counter object using sort on Object.entries and finally show only keys.
const arr = ["apples", "oranges", "oranges", "oranges",
"bananas", "bananas", "oranges"
];
// create a counter object on array
let counter = arr.reduce(
(counter, key) => {
counter[key] = 1 + counter[key] || 1;
return counter
}, {});
console.log(counter);
// {"apples": 1, "oranges": 4, "bananas": 2}
// sort counter by values (compare position 1 entries)
// the result is an array
let sorted_counter = Object.entries(counter).sort((a, b) => b[1] - a[1]);
console.log(sorted_counter);
// [["oranges", 4], ["bananas", 2], ["apples", 1]]
// show only keys of the sorted array
console.log(sorted_counter.map(x => x[0]));
// ["oranges", "bananas", "apples"]
Is there a better way to convert
["88 99", "20 99", "12 12"]
to a hashmap in the form
{"88": 1, "99": 2, "20": 1, "12": 1}
Using map or reduce?
Where in this case, a string with duplicate numbers only gets increases it's count by 1.
Currently I'm converting the above array into a 2d array using .split(' ')
and iterating over that 2d array in another for loop as so:
var counts = {}
for (let i = 0; i < logs.length; i++){
let ack = logs[i].split(' ');
if(ack[0]==ack[1]){
counts[ack[0]] = counts[ack[0]] ? counts[ack[0]] + 1 : 1;
}
else{
for(let j= 0; j < 2; j++){
counts[ack[j]] = counts[ack[j]] ? counts[ack[j]] + 1 : 1;
}
}
}
First I group by numbers, summing the appearances of each. This is using the reduce part. That's it. I used adaption of method by https://stackoverflow.com/a/62031473/3807365
var arr = ["88 99", "20 99", "12 12"]
var step1 = arr.reduce(function(agg, pair) {
pair.split(" ").forEach(function(item) {
agg[item] = (agg[item] || 0) + 1
})
return agg;
}, {})
console.log(step1)
Yes. I'm assuming you want to write in a functional style, so I'm not worrying about efficiency, etc.
You can collapse this into a hairy one-liner but I wrote the intermediate steps and output them for illustration.
const input = ["88 99", "20 99", "12 12"];
const split = input.map( (string) => string.split(" ") );
console.log("split: " + JSON.stringify(split));
const flattened = split.reduce( (acc,array) => acc = acc.concat(array), []);
console.log("flattened: " + JSON.stringify(flattened));
const output = flattened.reduce( (byKey, item) => {
if (!byKey[item]) byKey[item] = 0;
byKey[item]++;
return byKey;
}, {});
console.log(JSON.stringify(output))
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]])));
This question already has answers here:
Simplest code for array intersection in javascript
(40 answers)
Closed 3 years ago.
I have two arrays, and I want to be able to compare the two and only return the values that match. For example both arrays have the value cat so that is what will be returned. I haven't found anything like this. What would be the best way to return similarities?
var array1 = ["cat", "sum","fun", "run"];
var array2 = ["bat", "cat","dog","sun", "hut", "gut"];
//if value in array1 is equal to value in array2 then return match: cat
You can use :
const intersection = array1.filter(element => array2.includes(element));
Naturally, my approach was to loop through the first array once and check the index of each value in the second array. If the index is > -1, then push it onto the returned array.
βArray.prototype.diff = function(arr2) {
var ret = [];
for(var i in this) {
if(arr2.indexOf(this[i]) > -1){
ret.push(this[i]);
}
}
return ret;
};
β
My solution doesn't use two loops like others do so it may run a bit faster. If you want to avoid using for..in, you can sort both arrays first to reindex all their values:
Array.prototype.diff = function(arr2) {
var ret = [];
this.sort();
arr2.sort();
for(var i = 0; i < this.length; i += 1) {
if(arr2.indexOf(this[i]) > -1){
ret.push(this[i]);
}
}
return ret;
};
Usage would look like:
var array1 = ["cat", "sum","fun", "run", "hut"];
var array2 = ["bat", "cat","dog","sun", "hut", "gut"];
console.log(array1.diff(array2));
If you have an issue/problem with extending the Array prototype, you could easily change this to a function.
var diff = function(arr, arr2) {
And you'd change anywhere where the func originally said this to arr2.
I found a slight alteration on what #jota3 suggested worked perfectly for me.
var intersections = array1.filter(e => array2.indexOf(e) !== -1);
Hope this helps!
This function runs in O(n log(n) + m log(m)) compared to O(n*m) (as seen in the other solutions with loops/indexOf) which can be useful if you are dealing with lots of values.
However, because neither "a" > 1 nor "a" < 1, this only works for elements of the same type.
function intersect_arrays(a, b) {
var sorted_a = a.concat().sort();
var sorted_b = b.concat().sort();
var common = [];
var a_i = 0;
var b_i = 0;
while (a_i < a.length
&& b_i < b.length)
{
if (sorted_a[a_i] === sorted_b[b_i]) {
common.push(sorted_a[a_i]);
a_i++;
b_i++;
}
else if(sorted_a[a_i] < sorted_b[b_i]) {
a_i++;
}
else {
b_i++;
}
}
return common;
}
Example:
var array1 = ["cat", "sum", "fun", "hut"], //modified for additional match
array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
intersect_arrays(array1, array2);
>> ["cat", "hut"]
Loop through the second array each time you iterate over an element in the first array, then check for matches.
var array1 = ["cat", "sum", "fun", "run"],
array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
function getMatch(a, b) {
var matches = [];
for ( var i = 0; i < a.length; i++ ) {
for ( var e = 0; e < b.length; e++ ) {
if ( a[i] === b[e] ) matches.push( a[i] );
}
}
return matches;
}
getMatch(array1, array2); // ["cat"]
var array1 = [1, 2, 3, 4, 5, 6];
var array2 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var array3 = array2.filter(function(obj) {
return array1.indexOf(obj) !== -1;
});
You can use javascript function .find()
As it says in MDN, it will return the first value that is true. If such an element is found, find immediately returns the value of that element. Otherwise, find returns undefined.
var array1 = ["cat", "sum", "fun", "run", "cat"];
var array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
found = array1.find((val, index) => {
console.log('index', index) // Stops at 0
return array2.includes(val)
})
console.log(found)
Or use .filter(), which loops through every elements first, then give back the result to you.
var array1 = ["cat", "sum", "fun", "run", "cat"];
var array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
found = array1.filter((val, index) => {
console.log('index', index) // Stops at array1.length - 1
return array2.includes(val)
})
console.log(found)
use lodash
GLOBAL.utils = require('lodash')
var arr1 = ['first' , 'second'];
var arr2 = ['second '];
var result = utils.difference(arr1 , arr2);
console.log ( "result :" + result );
Libraries like underscore and lodash have a utility method called intersection to find matches in arrays passed in. Take a look at: http://underscorejs.org/#intersection
Done as a answer so I can do formatting...
This is the the process you need to go through. Looping through an array for the specifics.
create an empty array
loop through array1, element by element. {
loop through array2, element by element {
if array1.element == array2.element {
add to your new array
}
}
}
If your values are non-null strings or numbers, you can use an object as a dictionary:
var map = {}, result = [], i;
for (i = 0; i < array1.length; ++i) {
map[array1[i]] = 1;
}
for (i = 0; i < array2.length; ++i) {
if (map[array2[i]] === 1) {
result.push(array2[i]);
// avoid returning a value twice if it appears twice in array 2
map[array2[i]] = 0;
}
}
return result;
With some ES6:
let sortedArray = [];
firstArr.map((first) => {
sortedArray[defaultArray.findIndex(def => def === first)] = first;
});
sortedArray = sortedArray.filter(v => v);
This snippet also sorts the firstArr based on the order of the defaultArray
like:
let firstArr = ['apple', 'kiwi', 'banana'];
let defaultArray = ['kiwi', 'apple', 'pear'];
...
console.log(sortedArray);
// ['kiwi', 'apple'];
Iterate on array1 and find the indexof element present in array2.
var array1 = ["cat", "sum","fun", "run"];
var array2 = ["bat", "cat","sun", "hut", "gut"];
var str='';
for(var i=0;i<array1.length;i++){
if(array2.indexOf(array1[i]) != -1){
str+=array1[i]+' ';
};
}
console.log(str)
I'm looking for a good algorithm to get all the elements in one array that are not elements in another array. So given these arrays:
var x = ["a","b","c","t"];
var βββββββββy = [βββββββ"d","a","t","e","g"];
I want to end up with this array:
var z = ["d","e","g"];
I'm using jquery, so I can take advantage of $.each() and $.inArray(). Here's the solution I've come up with, but it seems like there should be a better way.
// goal is to get rid of values in y if they exist in x
var x = ["a","b","c","t"];
var y = ["d","a","t","e","g"];
var z = [];
$.each(y, function(idx, value){
if ($.inArray(value,x) == -1) {
z.push(value);
}
});
βalert(z); // should be ["d","e","g"]
Here is the code in action. Any ideas?
in ES6 simply
const a1 = ["a", "b", "c", "t"];
const a2 = ["d", "a", "t", "e", "g"];
console.log( a2.filter(x => !a1.includes(x)) );
(another option is a2.filter(x => a1.indexOf(x)===-1) )
Late answer with the new ECMA5 javascript:
var x = ["a","b","c","t"];
var y = ["d","a","t","e","g"];
myArray = y.filter( function( el ) {
return x.indexOf( el ) < 0;
});
var z = $.grep(y, function(el){return $.inArray(el, x) == -1});
Also, that method name is too short for its own good. I would expect it to mean isElementInArray, not indexOf.
For a demo with objects, see http://jsfiddle.net/xBDz3/6/
Here's an alternative using underscore.js:
function inAButNotInB(A, B) {
return _.filter(A, function (a) {
return !_.contains(B, a);
});
}
I am quite late now but maybe it will be helpful for someone.
If the array is not just a simple array but an array of objects then the following can be used:
var arr1 = [
{
"prop1": "value1",
"prop2": "value2",
},
{
"prop1": "value3",
"prop2": "value4",
},
{
"prop1": "value5",
"prop2": "value6",
},
];
var arr2 = ['value1','value3', 'newValue'];
// finds all the elements of arr2 that are not in arr1
arr2.filter(
val => !arr1.find( arr1Obj => arr1Obj.prop1 === val)
); // outputs "newValue"
This is a late answer, but it uses no libraries so some may find it helpful.
/**
* Returns a non-destructive Array of elements that are not found in
* any of the parameter arrays.
*
* #param {...Array} var_args Arrays to compare.
*/
Array.prototype.uniqueFrom = function() {
if (!arguments.length)
return [];
var a1 = this.slice(0); // Start with a copy
for (var n=0; n < arguments.length; n++) {
var a2 = arguments[n];
if (!(a2 instanceof Array))
throw new TypeError( 'argument ['+n+'] must be Array' );
for(var i=0; i<a2.length; i++) {
var index = a1.indexOf(a2[i]);
if (index > -1) {
a1.splice(index, 1);
}
}
}
return a1;
}
Example:
var sheetUsers = ['joe#example.com','fred#example.com','sam#example.com'];
var siteViewers = ['joe#example.com','fred#example.com','lucy#example.com'];
var viewersToAdd = sheetUsers.uniqueFrom(siteViewers); // [sam#example.com]
var viewersToRemove = siteViewers.uniqueFrom(sheetUsers); // [lucy#example.com]
findDiff = (A, B) => {
return A.filter(function (a) {
return !B.includes(a);
});
}
Make sorted copies of the arrays first. If the top elements are equal, remove them both. Otherwise remove the element that is less and add it to your result array. If one array is empty, then add the rest of the other array to the result and finish. You can iterate through the sorted arrays instead of removing elements.
// assume x and y are sorted
xi = 0; yi = 0; xc = x.length; yc = y.length;
while ( xi < xc && yi < yc ) {
if ( x[xi] == y[yi] ) {
xi += 1;
yi += 1;
} else if ( x[xi] < y[yi] ) {
z.push( x[xi] );
xi += 1;
} else {
z.push( y[yi] );
yi += 1;
}
}
// add remainder of x and y to z. one or both will be empty.
Maybe jLinq can help you?
It lets you run queries like this against javascript objects.
For example:
var users = [ { name: "jacob", age: 25 }, { name: "bob" , age: 30 }]
var additionalusers = [ { name: "jacob", age: 25 }, { name: "bill" , age: 25 }]
var newusers = jLinq.from(users).except(additionalusers).select();
>>> newusers = [ { name: "bob" , age: 30 } ]
It's a bit overkill for you at the moment, but it's a robust solution that I was glad to learn about.
It can do intersects, unions, handle boolean logic and all kinds of great linq style goodness.