Comparing and Filtering two arrays - javascript

I've been trying to implement a function where given with two arrays,
array1's elements is used as conditions to filter out elements in array2.
For instance:
array1= [apple, grapes, oranges]
array2= [potato, pears, grapes, berries, apples, oranges]
After feeding into a function, array2 should have elements as such:
filter_twoArrays(array1,array2)
array2= [grapes, apples, oranges]
I've tried the following code, using for loops and array.splice(), but the problem I am seeing is that when I use the splice method, it seems that it changes the lengths of array2 in the for loop:
function filter_twoArrays(filter,result){
for(i=0; i< filter.length; i++){
for(j=0; j< result.length; j++){
if(filter[i] !== result[j]){
result.splice(j,1)
}
}
}
Any inputs will be greatly appreciated on how to refine the filter function
cheers!

You can use filter as follow
var array1 = ['apples', 'grapes', 'oranges', 'banana'],
array2 = ['potato', 'pears', 'grapes', 'berries', 'apples', 'oranges'];
var intersection = array1.filter(function(e) {
return array2.indexOf(e) > -1;
});
console.log(intersection);
You can also add this method on Array prototype and call it directly on array
Array.prototype.intersection = function(arr) {
return this.filter(function(e) {
return arr.indexOf(e) > -1;
});
};
var array1 = ['apples', 'grapes', 'oranges', 'banana'],
array2 = ['potato', 'pears', 'grapes', 'berries', 'apples', 'oranges'];
var intersection = array1.intersection(array2);
console.log(intersection);

You can use some, like this:
let newArray = array2.filter(
(array22) => !array1.some((array11) => array11.id === array22._id));

Hi this is a porting of the function array_intersect php. Should be good for you
http://phpjs.org/functions/array_intersect/
function array_intersect(arr1) {
// discuss at: http://phpjs.org/functions/array_intersect/
// original by: Brett Zamir (http://brett-zamir.me)
// note: These only output associative arrays (would need to be
// note: all numeric and counting from zero to be numeric)
// example 1: $array1 = {'a' : 'green', 0:'red', 1: 'blue'};
// example 1: $array2 = {'b' : 'green', 0:'yellow', 1:'red'};
// example 1: $array3 = ['green', 'red'];
// example 1: $result = array_intersect($array1, $array2, $array3);
// returns 1: {0: 'red', a: 'green'}
var retArr = {},
argl = arguments.length,
arglm1 = argl - 1,
k1 = '',
arr = {},
i = 0,
k = '';
arr1keys: for (k1 in arr1) {
arrs: for (i = 1; i < argl; i++) {
arr = arguments[i];
for (k in arr) {
if (arr[k] === arr1[k1]) {
if (i === arglm1) {
retArr[k1] = arr1[k1];
}
// If the innermost loop always leads at least once to an equal value, continue the loop until done
continue arrs;
}
}
// If it reaches here, it wasn't found in at least one array, so try next value
continue arr1keys;
}
}
return retArr;
}

You can use
const arr1 = [1, 2, 3];
const arr2 = [2, 3];
arr1.filter(e => arr2.indexOf(e) > -1 ? false : true); // [1]

Came here some week back to find a solution to a problem like this but its a pity I couldn't get what I wanted, but now I figured it out in a more simple way. using the arrow function, .filter() method and .includes() method.
Declare an arrow function that takes in two arguments:
const filterTwoArrays = (string1, string2) => string1.filter(item => string2.includes(item));
console.log(filterTwoArrays(array1, array2)).

Here is one simple way based on your code
function array_filter(filter, result) {
var filterLen = filter.length;
var resultLen = result.length;
for (i = 0; i < resultLen; i++) {
for (j = 0; j < filterLen; j++) {
if (!contains(filter, result[i]))
result.splice(i, 1);
}
}
}
//Return boolean depending if array 'a' contains item 'obj'
function contains(array, value) {
for (var i = 0; i < array.length; i++) {
if (array[i] == value) {
return true;
}
}
return false;
}

Since you have tagged javascript here is the solution.
function f1(x, y) {
var t = y.slice(0);
var r = [];
for (var i = 0; i < x.length; i++) {
for (var j = 0; j < y.length; j++) {
if (x[i] === y[j]) {
[].push.apply(r, t.splice(j, 1));
}
}
}
console.log(r)
y.length = 0;
[].push.apply(y, r);
}

Mark the items which are to be filtered out via delete result[index] manipulate them as needed.
JavaScript
window.onload = runs;
function runs() {
var array1 = ["apples", "grapes", "oranges"];
var array2 = ["potato", "pears", "grapes", "berries", "apples", "oranges"];
var result = filter_twoArrays(array1, array2);
function filter_twoArrays(filter, result) {
var i = 0,
j = 0;
for (i = 0; i < result.length; i++) {
var FLAG = 0;
for (j = 0; j < filter.length; j++) {
if (filter[j] == result[i]) {
FLAG = 1;
}
}
if (FLAG == 0) delete result[i];
}
return result;
}
var body = document.getElementsByTagName("body")[0];
var i = 0;
for (i = 0; i < result.length; i++) {
if (result[i] !== undefined)
body.innerHTML = body.innerHTML + result[i] + " ";
}
}

const func = array1.filter(item => array2.includes(item));

Related

JS find an array's element is in another array or not

I am new to JS and I want to check an array's element in another array or not, also want to add to the array if not exist.
Here has 2 arrays:
let array1 = [[1,3,'Betty','Betty#email.com'],[2,5,'Mary','Mary#email.com'],[3,73,'Tom','Tom#email.com']]
let array2 = [[1,3,'Betty','Betty#email.com'],[9,25,'Jo','Jo#email.com'],[10,733,'Louis','Louis#email.com']]
Then I want to check the every single element of array2 is in array1 or not, and checking by the name or mail address, also push it to array1 if not.
But I don't know what's the method to do it, please help. Many Thanks!!
In my version I first create a dictionary object dict that helps me find an existing element in array1 and then I step through all the elements of array2 and push them onto array1 if the combination of both, name and mail address is not yet in array1.
const array1 = [[1,3,'Betty','Betty#email.com'],[2,5,'Mary','Mary#email.com'],[3,73,'Tom','Tom#email.com']],
array2 = [[1,3,'Betty','Betty#email.com'],[9,25,'Jo','Jo#email.com'],[10,733,'Louis','Louis#email.com']];
const dict=array1.reduce((a,c)=>
(a[c.slice(2).join('|')]=1,a),{});
array2.forEach(c=>dict[c.slice(2).join('|')]||array1.push(c))
console.log(array1)
This is my solution. I have created 2 function
The first one. This function will check if data is in array or not.
Note: This function is work around only to this question (Array nested within array)
function isExistInArray(data, array) {
for (let i = 0; i < array.length; i++) {
let isExist = true
for (let j = 0; j < data.length; j++) {
if (data[j] !== array[i][j]) {
isExist = false
}
}
if (isExist) {
return true
}
}
return false
}
And the second one is function to add item in array2 into array1 if it isn't exist.
function combineArray(arr1, arr2) {
const result = [...arr1]
arr2.forEach(item => {
if (!isExistInArray(item, arr1)) {
result.push(item)
}
})
return result
}
And then this code is now working!
Here is full code
let array1 = [[1, 3, 'Betty', 'Betty#email.com'], [2, 5, 'Mary', 'Mary#email.com'], [3, 73, 'Tom', 'Tom#email.com']]
let array2 = [[1, 3, 'Betty', 'Betty#email.com'], [9, 25, 'Jo', 'Jo#email.com'], [10, 733, 'Louis', 'Louis#email.com']]
function isExistInArray(data, array) {
for (let i = 0; i < array.length; i++) {
let isExist = true
for (let j = 0; j < data.length; j++) {
if (data[j] !== array[i][j]) {
isExist = false
}
}
if (isExist) {
return true
}
}
return false
}
function combineArray(arr1, arr2) {
const result = [...arr1]
arr2.forEach(item => {
if (!isExistInArray(item, arr1)) {
result.push(item)
}
})
return result
}
console.log(combineArray(array1, array2))
Here you can use this, but first understand what you are doing.
for(let i = 0; i < array2.length; i++) {
for(let j = 0; j < array1.length; j++) {
// If name or email matches break
if(array1[j][2] === array2[i][2] || array1[j][3] === array2[i][3]) {
break;
} else {
// If it comes here than that means email or name does not match so pushing it
if(j === array1.length - 1) { // Last Element
array1.push(array2[i])
}
}
}
}
Find variable is array or not
const arr = [{name:'vishal'},{name:'Rahul'}];
if(Array.isArray(arr)){
console.log("array")
}
else{
console.log('not array');
}

How do I build an object counting occurrences in an Array in JavaScript?

I want to count how often a number in an Array occurs. For example, in Python I can use Collections.Counter to create a dictionary of how frequently an item occurs in a list.
This is as far as I've gotten in JavaScript:
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
/* obj[array[i]] = +=1 */ <= pseudo code
}
How can I create this frequency counter object?
Close but you can't increment undefined so you need to set initial value if it doesn't exist
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = (obj[array[i]] || 0) +1 ;
}
You were almost there. See below code:
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = (obj[array[i]] || 0 ) +1;
}
console.log(obj);
Create an object and check if that specific key exist.If exist then increase it's value by 1
var array = [1, 4, 4, 5, 5, 7];
var obj = {};
for (var i = 0; i < array.length; i++) {
if (obj.hasOwnProperty(array[i])) {
obj[array[i]] += 1;
} else {
obj[array[i]] = 1;
}
}
console.log(obj)
You can use the ? : ternary operator to set initial value as 1 and then increment it on subsequent matches.
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = obj[array[i]]?obj[array[i]]+1:1;
}
console.log(obj);
If the array is always going to be same, and you are going to check frequency of multiple items in the same array without it it being modified, #JohanP's answer is good.
But if you are only going to check frequency of only one item, or the array can change, creating the object is nothing but extra overhead.
In that case, you can do something like this:
const getItemFrequency = function(array, item) {
return array.filter(i => i === item).length;
}
var array = [1,4,4,5,5,7];
console.log(getItemFrequency(array, 4));
Concise logic written as proper function:
function countArrayItemFrequecy(array) {
const length = array.length;
const map = {};
for ( let i = 0; i < length; i++ ) {
let currentItem = array[i];
if (typeof map[currentItem] !== 'undefined' ) {
map[currentItem]++
} else {
map[currentItem] = 1
}
}
return map;
}
You need to make sure to assign default value to your frequency object for the first occurrence of the item. As a shortcut you can use ternary operator
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
obj[array[i]] = obj[array[i]] ? obj[array[i]]++ : 1;
}
which is the same as:
var array = [1,4,4,5,5,7];
var obj = {};
for (var i=0; i < array.length; i++) {
if (obj[array[i]]) {
obj[array[i]]++;
} else {
obj[array[i]] = 1;
}
}
You can use Object.assign: below clones map and then increments/adds the counter. These are pure (no side effects/param reassignment), single-purpose functions.
addToMap does the same thing as { ...map, map[e]: [e]: (map[e] || 0) + 1 }, but that requires babel.
const addToMap = (map, e) => Object.assign({}, map, { [e]: (map[e] || 0) + 1 });
const buildMap = a => a.reduce(addToMap, {});
Using Array.reduce:
arr.reduce(function (acc, item) {
acc[item] = (acc[item] || 0) + 1;
return acc;
}, {});
Example:
var arr = [1,1,2,4,1,4];
var counts = arr.reduce(function (acc, item) {
acc[item] = (acc[item] || 0) + 1;
return acc;
}, {});
console.log(counts);

Why is this function returns an empty array?

I just don't understand why does this function return an empty array instead of newArr = [1, 2, 3, etc.] depending on the length of the array.
function randomFunction(num) {
var newArr = [];
for(var i = 1; i < num.length; i++) {
newArr.push(i);
}
return newArr;
};
If num is supposed to be the length of the new array, and the last number of the range of values, you have to use it directly, instead of using length (which is meant to be used for an array):
function randomFunction(num) {
var newArr = [];
for(var i = 1; i <= num; i++) {
newArr.push(i);
}
return newArr;
};
var array = randomFunction(5);
console.log(array);
Also, you might want use <= instead of <, in case you want to start the value by 1 and go through n, and not n - 1.
function randomFunction(num) {
var newArr = [];
for(var i = 1; i < num /* number has no length */; i++) {
newArr.push(i);
}
return newArr;
};
Es6 alternative for fun:
return new Array(num).fill().map((r, i) => i)
randomFunction(8) ; for example
A number doesn't have length at all. It's already a value.
You do not need length attribute at all. just
for(var i = 1; i < num; i++) {
newArr.push(i);
}
function randomFunction(num) {
var newArr = [];
for (var i = 1; i < num; i++) {
newArr.push(i);
}
return newArr;
};
console.log(randomFunction(8))
num is already a number. You don't need use .lenght property
function randomFunction(num) {
var newArr = [];
for(var i = 1; i <= num; i++) {
newArr.push(i);
}
return newArr;
};
randomFunction(5); // [ 1, 2, 3, 4, 5 ]

How to get subset of two arrays into a different array using javascript?

i have 2 arrays.
arr1=[1,8,1,3,2]
arr2=[3,8,1]
I want to put elements [8,1] subset into arr3. How can i do this using javascript?I used the following code. But doesn't seemed to be working.
function subsetFind() {
var arr1 = [1,8,1,3,2]
var arr2 = [3,8,1]
var arr3 = [];
var arr1length = arr1.length;
var arra2length = arr2.length;
for(var i = 0; i < arr1length; ++i){
for(var j=0;j<arra2length;j++) {
if(arr1[i] != arr2[j]) {
break;
} else {
arr3.push(arr1[i]);
break;
}
}
}
alert(arr3);
}
Try this solution - it checks whether both current and previous OR current and next value is equal:
function subsetFind() {
var arr1 = [1,8,1,3,2]
var arr2 = [3,8,1]
var arr3 = [];
var arr1length = arr1.length;
var arra2length = arr2.length;
var used_i = 0;
for(var i = 0; i < arr1length; ++i){
if(used_i != 0 && used_i < i-1){
break;
}
for(var j=0;j<arra2length;j++) {
if((arr1[i] == arr2[j] && arr1[i-1] == arr2[j-1]) || (arr1[i] == arr2[j] && arr1[i+1] == arr2[j+1])) {
arr3.push(arr1[i]);
used_i = i;
}
}
}
alert(arr3);
}
Output:
8,1
I hope that you want; (renewed :)
function subset() {
var arr1 = [1, 9, 3, 5, 4, 8, 2, 6, 3, 4]
var arr2 = [5, 2, 4, 8, 2, 6, 4]
var arr3 = [];
var minSize=2; // minimum 2 element must in intersection
var findedMax = "";
var arr1Joined = ""; arr1.forEach(function (a) { arr1Joined += "," + a; });
for(k=minSize;k<arr2.length;k++)
arr2.forEach(function (x,y) {
var fkey="";
for (i = y; i <= y+k; i++)
fkey += "," + arr2[i];
if (arr1Joined.indexOf(fkey) >= 0) findedMax = fkey;
});
arr3=findedMax.substr(1).split(",");
alert(arr3);
}
Try This Out:
Reference n-dru's answer:
function subset () {
var arr1 = [1,9,3,5,4,8,2,6,3,4]
var arr2 = [5,2,4,8,2,6,4]
var arr3 = [];
var arr1length = arr1.length;
var arra2length = arr2.length;
var finalResult;
for(var i = 0; i < arr1length; ++i){
for(var j=0;j<arra2length;j++) {
if((arr1[i] == arr2[j] && arr1[i-1] == arr2[j-1]) || (arr1[i] == arr2[j] && arr1[i+1] == arr2[j+1])) {
arr3.push(arr1[i]);
}
else
{
finalResult = arr3.toString();
}
}
}
alert(finalResult);
}
DEMO
I believe Your question was alredy answerd in: Simplest code for array intersection in javascript and Finding matches between multiple JavaScript Arrays . You can also look into implementation of _.intersection in lowdash library.
ES6 way.
[...new Set(arr1)].filter(v => arr2.includes(v))
Break down:
new Set(arr1) // convert arr1 to Set to remove duplicates
[...new Set(arr1)] // convert back to array
arr2.includes(v) // test if arr2 includes `v`
[...new Set(arr1)].filter(v => arr2.includes(v)) // choose unique elements in both arrays

Counting unique words in strings

Below I am trying to give string arrays to a function that adds unique words to a words array, and if the word is already in the array to increase the count of the corresponding element in the count array:
var words = [];
var counts = [];
calculate([a, b]);
calculate([a, c]);
function calculate(result) {
for (var i = 0; i < result.length; i++) {
var check = 0;
for (var j = 0; i < tags.length; i++) {
if (result[i] == tags[j]) {
check = 1;
counts[i] = counts[i] + 20;
}
}
if (check == 0) {
tags.push(result[i]);
counts.push(20);
}
check = 0;
}
}
However the output turns out like this:
words = a, b
count = 2, 1
When I expect it to be:
words = a,b,c
count = 2,1,1
Thanks for any help in advance
Breaking the problem down into methods with good names helps you to work out your logic.
Try this:
<script type="text/javascript">
var words = [];
var counts = [];
calculate(["a", "b"]);
calculate(["a", "c"]);
console.log(words);
console.log(counts);
function calculate(result) {
for (var i=0; i<result.length; i++) {
if (array_contains(words, result[i])) {
counts[result[i]]++;
} else {
words.push(result[i]);
counts[result[i]] = 1;
}
}
}
function array_contains(array, value) {
for (var i=0; i<array.length; i++)
if (array[i] == value)
return true;
return false;
}
</script>
Output:
["a", "b", "c"]
[]
a 2
b 1
c 1
Please check this :
you can test it on : http://jsfiddle.net/knqz6ftw/
var words = [];
var counts = [];
calculate(['a', 'b']);
calculate(['a', 'c']);
calculate(['a', 'b', 'c']);
function calculate(inputs) {
for (var i = 0; i < inputs.length; i++) {
var isExist = false;
for (var j = 0; j < words.length; j++) {
if (inputs[i] == words[j]) {
isExist = true
counts[i] = counts[i] + 1;
}
}
if (!isExist) {
words.push(inputs[i]);
counts.push(1);
}
isExist = false;
}
}
console.log(words);
console.log(counts);
Output is :
["a", "b", "c"] (index):46
[3, 2, 2]
A few things were wrong, here's working code:
var words = [];
var counts = [];
calculate(["a", "b"]);
calculate(["a", "c"]);
function calculate(result) {
for (var i = 0; i < result.length; i++) {
var check = 0;
for (var j = 0; j < words.length; j++) {
if (result[i] == words[j]) {
check = 1;
++counts[j];
}
}
if (check == 0) {
words.push(result[i]);
counts.push(1);
}
check = 0;
}
}
Jsbin : http://jsbin.com/hawaco/2/edit?js,console
Things I've changed:
Changed array literal to supply strings instead of variable names: [a,b] to ["a","b"]
Replaced instances of tags (presumably an old name) with words
Changed the 20s to 1s
Made the increment of counts[j] more clear
Fixed use of i/j indices
Things to consider:
Perhaps make this a dictionary rather than a pair of arrays: {"a":1, "b":2}, which would make for simpler code
Pass in the names of the arrays to permit other accumulators, or combine the method and arrays into a single object
Simplified:
var seen = {};
count(["a", "b"], seen);
count(["a", "c"], seen);
function count(words, accumulator) {
for (var i = 0; i < words.length; ++i) {
if(!accumulator.hasOwnProperty(words[i])) {
accumulator[words[i]] = 1;
} else {
++accumulator[words[i]];
}
}
}
Result:
>> seen
[object Object] {
a: 2,
b: 1,
c: 1
}
JSBin: http://jsbin.com/halak/1/edit?js,console
Here's my solution (using an object):
const checkWord = (str) => {
let collection = {};
// split the string into an array
let words = str.split(' ');
words.forEach((word) => {
collection[word] = word;
});
// loop again to check against the array and assign a count
for (let j = 0; j < words.length; j++) {
if (words[j] === collection[words[j]]) {
collection[words[j]] = 0;
}
collection[words[j]]++
}
console.log(collection);
};
You can also use reduce:
const checkWord = (str) => {
let collection = {};
let words = str.split(' ');
words.forEach((word) => {
collection[word] = word;
});
for (var i = 0; i < words.length; i++) {
if (words[i] === collection[words[i]]) {
collection[words[i]] = 0;
}
}
let total = words.reduce((occurrences, word) => {
collection[word]++
return collection;
}, 0);
console.log(total);
};

Categories

Resources