JavaScript - Check every element of 2D arrays for match - javascript

I am trying to compare an array of elements with the elements of a 2D array. If there is a match found, then the count for that row of 2D elements will increase. I managed to do it with the first row of 2D array however I do not know how to make the code keep checking for the next row of the 2D array.
var fruits=[
['apple', 'banana', 'mango'],
['grape', 'pineapple', 'blueberry'],
['strawberry', 'mangosteen']
];
var fruit_i_like=[
['grape', 'banana', 'pineapple']
];
//if found match from the first row of fruits, increment this var
var fruit1_count = 0;
//if found match from the second row of fruits, increment this var
var fruit2_count = 0;
//if found match from the third row of fruits, increment this var
var fruit3_count = 0;
for (var i = 0; i < fruit_i_like.length; i++) {
for (var j = 0; j < fruits.length; j++){
if (fruits[j].indexOf(fruit_i_like[i]) > -1) {
fruit1_count++;
}
}
}
The expected result should be printing the number of match the fruit_i_like array has with every rows of the array fruits. For example, here fruit1_count would be 1, fruit2_count would be 2, fruit3_count would be 0.
Is there any way of checking the other rows, using pure JS? Thank you!

Probably better to use an array than variables in this case, so you don't have to hardcode names and definitions. In this case, you'll get an ordered list of each fruit's count at the end from the array, in the order you initially put them in the fruits array (not sure why fruit_i_like is two-dimensional, either).
var fruits = [
['apple', 'banana', 'mango'],
['grape', 'pineapple', 'blueberry'],
['strawberry', 'mangosteen']
];
var fruit_i_like = [
['grape', 'banana', 'pineapple']
];
let fruitCounts = [];
fruits.forEach((fruitsList, i) => {
fruitCounts.push(0);
fruit_i_like[0].forEach(likedFruit => {
if (fruitsList.includes(likedFruit)) {
fruitCounts[i]++;
}
});
});
fruitCounts.forEach((count, i) => {
console.log(`Fruit count ${i} = ${count}`);
});

1) You can easily achieve the result using Set and simple for loop. You can first create an object of properties in which count you want as:
const obj = {
fruit1_count: 0,
fruit2_count: 0,
fruit3_count: 0,
};
var fruits = [
["apple", "banana", "mango"],
["grape", "pineapple", "blueberry"],
["strawberry", "mangosteen"],
];
var fruit_i_like = [["grape", "banana", "pineapple"]];
const obj = {
fruit1_count: 0,
fruit2_count: 0,
fruit3_count: 0,
};
const set = new Set(fruit_i_like[0]);
for (let i = 0; i < fruits.length; ++i) {
const arr = fruits[i];
for (let j = 0; j < arr.length; ++j) {
if (set.has(arr[j])) obj[`fruit${i + 1}_count`]++;
}
}
const { fruit1_count, fruit2_count, fruit3_count } = obj;
console.log(fruit1_count);
console.log(fruit2_count);
console.log(fruit3_count);
2) You can also use reduce and forEach here as:
var fruits = [
["apple", "banana", "mango"],
["grape", "pineapple", "blueberry"],
["strawberry", "mangosteen"],
];
var fruit_i_like = [["grape", "banana", "pineapple"]];
const obj = {
fruit1_count: 0,
fruit2_count: 0,
fruit3_count: 0,
};
const set = new Set(fruit_i_like[0]);
const resultObj = fruits.reduce((acc, curr, i) => {
curr.forEach((o) => {
if (set.has(o)) acc[`fruit${i + 1}_count`]++;
});
return acc;
}, obj);
const { fruit1_count, fruit2_count, fruit3_count } = resultObj;
console.log(fruit1_count);
console.log(fruit2_count);
console.log(fruit3_count);

I'm a little late to the party, but you can also do this with a pair of nested Array.reduce() methods, and using Array.includes() in the nested reduce to increment the count if included in the array.
const fruits = [
['apple', 'banana', 'mango'],
['grape', 'pineapple', 'blueberry'],
['strawberry', 'mangosteen']
];
const fruit_i_like = [
['grape', 'banana', 'pineapple']
];
const [fruit1_count, fruit2_count, fruit3_count] = fruits.reduce((a, c, i) => {
a[i] = fruit_i_like[0].reduce((aa, cc) => aa + c.includes(cc), 0);
return a;
}, new Array(fruits.length));
console.log({
fruit1_count: fruit1_count,
fruit2_count: fruit2_count,
fruit3_count: fruit3_count
})

Related

How can I get all words that contain a particular letter from an array?

How to find elements of an array that contain the letter a, and insert them into a temporary array?
const fruits = ['banana', 'mango', 'apple', 'kiwi', 'lemons', 'limes'];
function letterA (fruits){
const tempArray = [];
for (i = 0; i < fruits.length; i++) {
if (fruits.includes('a')) {
fruits.push(tempArray[i]);
}
if (tempArray.length) {
return tempArray;
} else {
console.log ("No elements with character 'a' found");
}
}
}
letterA(fruits);
You can use the filter method:
const fruits = ['banana', 'mango', 'apple', 'kiwi', 'lemons', 'limes'];
const filtered = fruits.filter(fruit => fruit.includes('a'))
console.log(filtered)
This is a fix of your code using for loop. The if statement must check if fruits[i] includes 'a', then push to tempArray if true. Then checks if the tempArray has any elements and if so, it returns the tempArray. If not, it returns the string "No elements with character 'a' found".
const fruits = ['banana', 'mango', 'apple', 'kiwi', 'lemons', 'limes'];
function letterA (fruits){
const tempArray = [];
for (let i = 0; i < fruits.length; i++) {
if (fruits[i].includes('a')) {
tempArray.push(fruits[i]);
}
}
if (tempArray.length) {
return tempArray;
} else {
return "No elements with character 'a' found";
}
}
let result = letterA(fruits);
console.log(result)
here is the solution with for - of loop:
const fruits = ['banana', 'mango', 'apple', 'kiwi', 'lemons', 'limes'];
const result = [];
for (const item of fruits) {
if(item.includes('a')){
result.push(item);
}
}
console.log(result)

how to filter array items in js without filter method?

here is the question
Filter out companies which have more than one 'o' without the filter method
0: "Facebook"
1: "Google"
2: "Microsoft"
3: "Apple"
4: "IBM"
5: "Oracle"
6: "Amazon"
You need to loop through the array and check if each word has more than one "o".
Here is a function to verify the word:
const verif=(word)=>{
var s=0
var l=word.length
for(let i=0 ; i<=l;i++) {
if (word[i]=="o") {
s++
}
}
if (s>=2) {
return true
} else {
return false
}
}
const itCompanies = ['Facebook', 'Google', 'Microsoft', 'Apple', 'IBM', 'Oracle', 'Amazon' ]
let OCompanies = []; // declare an empty array for 'O' letter companies
// use for loop to loop through itCompanies array
for (let index = 0; index < itCompanies.length; index++) {
// get individual element of the array
const company = itCompanies[index];
// using split method, you can split the string based on the delimeter 'o'. you can then use length method of the array to determine the number of occurances
const count = company.split('o').length - 1;
// check if the company contains more than one 'o'
if (count > 1) {
// use push method to add elements to the OCompanies array
OCompanies.push(company)
}
}
console.log(OCompanies) // ['Facebook', 'Google', 'Microsoft']
You can try this way:-
const itCompanies = ['Facebook', 'Google', 'Microsoft', 'Apple', 'IBM', 'Oracle', 'Amazon']
const zeroContaineCompany = []
for(let i=0; i<itCompanies.length; i++){
if(itCompanies[i].includes('o')){
const zeroCount = itCompanies[i].toLowerCase().split('');
let count = 0
for(let j=0; j< zeroCount.length; j++){
if( zeroCount[j] === 'o'){
count += 1
}
}
if(count>1){
zeroContaineCompany.push(itCompanies[i])
}
}
}
console.log(zeroContaineCompany)
You can create a function a iterate through each array element
function filterArray(arr, fn) {
let filteredArray = [];
for (let i = 0; i < arr.length; ++i) {
if (fn(arr[i]) === true) {
filteredArray.push(arr[i]);
}
}
return filteredArray;
}
function isIsogram (str) {
return !/(.).*\1/.test(str);
}
const arr = ["Facebook", "Google", "Microsoft", "Apple", "IBM", "Oracle", "Amazon"];
console.log(filterArray(arr, isIsogram));

Count instances of string in a very large array and add the value to a hash value

I have a very large array of words in an array, and I want to count all of them and add the count as a value to each string.
So I for example:
words = ["a", "hello", "hello", "b", "went", "a"]
I want to convert this into:
words = [{"a" => 2}, {"b" => 1}, {"hello" => 2}, {"went" => 1}]
I have seen ways to simply count one word in a string and return its occurrences, but how might I do this at a large scale, while creating an array of hashes with the number of occurrences?
I can remove duplicate values after, I am more interested in the process of counting the values and adding the count as values in a hash.
In first turn you can create an object with the array value and number of occurrence.Then loop through it to create an array of objects
var words = ["a", "hello", "hello", "b", "went", "a"];
var rObj = {};
var finalArray = [];
words.map(function(currentValue, index) {
if (rObj.hasOwnProperty(currentValue)) {
rObj[currentValue] = rObj[currentValue] + 1;
} else {
rObj[currentValue] = 1
}
});
for (var keys in rObj) {
var obj = {};
obj[keys] = rObj[keys];
finalArray.push(obj)
};
console.log(finalArray)
You can first use reduce() to count elements and return object and then map() to return array of object values.
var words = ["a", "hello", "hello", "b", "went", "a"]
var count = words.reduce(function(r, e) {
if(!r[e]) r[e] = {[e]: 1}
else r[e][e] += 1
return r;
}, {})
var result = Object.keys(count).map(e => count[e])
console.log(result)
For a really huge array, I suggest to use either a while of a for loop and a plain check if the key with the word exist. If not assign zero to it. Later increment the property of the count object.
At last convert the object into an array with the wanted structure.
var words = ["a", "hello", "hello", "b", "went", "a"],
w,
i = words.length,
count = Object.create(null),
result;
while (i--) {
w = words[i];
if (!count[w]) {
count[w] = 0;
}
count[w]++;
}
result = Object.keys(count).map(function (k) {
var temp = {};
temp[k] = count[k];
return temp;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Don't count repeaters by hashing. Use a while loop for smaller overhead. Assignments over calculation. You will get an answer on orders of magnitude 5 times faster. One million words randomly generated from 12 words in a 1/5th of the time.
var wordsArray = ['apple', 'beer', 'cake', 'potato', 'orange', 'monitor', 'program', 'application', 'keyboard', 'javascript', 'gaming', 'network'],
words = [];
for (i = 0; i < 1000000; i++) {
words.push(wordsArray[Math.floor(Math.random() * wordsArray.length)]);
}
function getCount(words) {
var w,
i = words.length,
hash = {};
while (i--) {
w = words[i];
if (!hash[w]) {
hash[w] = 0;
}
hash[w]++;
}
return hash
}
console.time('Obj-time');
var counts = getCount(words);
array = [];
for (let i in counts) {
var l = i.length,
val = counts[i];
array.push({
[i]: val * l
})
}
console.log(array);
console.timeEnd('Obj-time');

How to merge arrays in javascript in a different way?

I want to merge arrays a little bit different way.
I have 2 or more arrays like:
var array1 = ["apple", "banana"];
var array2 = ["apple", "apple", "orange"];
I want the output:
var array3 = ["apple", "apple", "banana", "orange"];
So if any given array has a variable in it more than once, merge algorithm should keep all of them from that array.
I saw some code that prevents duplication but it gives outputs like this:
var array3 = ["apple", "banana", "orange"];
for more example:
var arr1 = [1,2,3,4];
var arr2 = [1,1,2,4,5,5,5];
var arr3 = [1,3,3,5,5];
I want the output:
var array4 = [1,1,2,3,3,4,5,5,5];
How can I do this?
Here's one way to do it by counting the occurrences of each item in each array:
var arr1 = [1,2,3,4];
var arr2 = [1,1,2,4,5,5,5];
var arr3 = [1,3,3,5,5];
function joinCommon(/* list of arrays */) {
var arr, arrayCounts, masterList = {}, item, output;
// for each array passed in
for (var i = 0; i < arguments.length; i++) {
arr = arguments[i];
arrayCounts = {};
// iterate each array
for (var j = 0; j < arr.length; j++) {
item = arr[j];
if (!arrayCounts[item]) {
arrayCounts[item] = 1;
} else {
++arrayCounts[item];
}
// now keep master list and master counts
if (!masterList[item]) {
masterList[item] = {cnt: 1, val: item};
} else {
masterList[item].cnt = Math.max(masterList[item].cnt, arrayCounts[item]);
}
}
}
// now output result
output = [];
for (var i in masterList) {
for (var j = 0; j < masterList[i].cnt; j++) {
output.push(masterList[i].val);
}
}
return output;
}
var results = joinCommon(arr1, arr2, arr3);
Working demo: http://jsfiddle.net/jfriend00/dtn6zw4m/
Here is a solution using ECMA5.
Javascript
function indexOf(items, value) {
return items.map(function (subitem) {
return subitem.value;
}).indexOf(value);
}
function countItems(previous, item) {
var atIndex = indexOf(previous, item);
if (atIndex !== -1) {
previous[atIndex].count += 1;
} else {
previous.push({
value: item,
count: 1
});
}
return previous;
}
function mergeCounts(item) {
var atIndex = indexOf(this, item.value);
if (atIndex === -1) {
this.push(item);
} else if (this[atIndex].count < item.count) {
this[atIndex] = item;
}
}
function expandCounts(previous, item) {
var iter;
for (iter = 0; iter < item.count; iter += 1) {
previous.push(item.value);
}
return previous;
}
function mergeArg(items, arg) {
arg.reduce(countItems, []).forEach(mergeCounts, items);
return items;
}
function mergeMaxItems() {
return [].reduce.call(arguments, mergeArg, []).reduce(expandCounts, []);
}
var arr1 = [1, 2, 3, 4],
arr2 = [1, 1, 2, 4, 5, 5, 5],
arr3 = [1, 3, 3, 5, 5];
document.body.appendChild(document.createTextNode(mergeMaxItems(arr1, arr2, arr3)));
I like to use ramda (http://ramdajs.com/docs/index.html) for this stuff
var arr1 = [1,2,3,4];
var arr2 = [1,1,2,4,5,5,5];
var arr3 = [1,3,3,5,5];
var allArrays = [arr1, arr2, arr3];
var allValues = R.compose(R.uniq, R.flatten)(allArrays);
var getItemCounts = R.countBy(function(item) {
return item;
});
var itemCounts = R.map(function(arr) {
return getItemCounts(arr);
})(allArrays);
var combined = [];
R.forEach(function(item) {
var countsForItem = R.pluck(item, itemCounts);
var maxCount = R.max(countsForItem);
combined.push.apply(combined, R.repeatN(item, maxCount));
})(allValues);
console.log(combined.sort());
JSFiddle: http://jsfiddle.net/pcr0q1xa/3/
Ramda is your friend.
function merge () {
return R.chain(R.apply(R.repeat), R.toPairs(R.reduce(
R.mergeWith(R.max),
{},
R.map(R.countBy(R.identity), arguments)
)))
}
var array1 = ["apple", "banana"];
var array2 = ["apple", "apple", "orange"];
console.log(JSON.stringify(merge(array1, array2)))
var arr1 = [1,2,3,4];
var arr2 = [1,1,2,4,5,5,5];
var arr3 = [1,3,3,5,5];
console.log(JSON.stringify(merge(arr1, arr2, arr3)))
<script src="http://cdnjs.cloudflare.com/ajax/libs/ramda/0.22.1/ramda.min.js"></script>
Untested and not JS, but I think this is what you are looking for.
I have just tested it manually, it worked for your test cases.
while items in lista or items in listb
compare a.head, b.head
if a.head is smaller or b.is_empty then
append a.head to output
a.drophead
else if b.head is smaller or a.is_empty then
append b.head to output
b.drophead
else
append b.head to output
b.drophead
a.drophead

How can I find matching values in two arrays? [duplicate]

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)

Categories

Resources