count values in each object of array - javascript

Sorry I've just changed this question :
I would like to know how many times I have THE WORD "orange" in my array. In this example "orange" > 4 times.
MyArray = [{
fruit1: "Orange is blabla",
fruit2: "Apple blabla",
fruit3: "blabla Banana",
color1: "ORANGE"
}, {
fruit4: "blabla Orange",
fruit5: "Apple",
fruit6: "Banana",
color2: "orange blabla"
}];
var newArr = MyArray.filter(function (item) {
return _.values(item.xxx === "orange";
});

You can do it in the following way
let MyArray = [{fruit1:"Orange", fruit2:"Apple", fruit3:"Banana", color1:"ORANGE"},{fruit4:"Orange", fruit5:"Apple", fruit6:"Banana", color2:"orange"}];
let result = MyArray.reduce((a, b) => {
for(let key of Object.keys(b)){
let re = /orange/gi;
if(b[key].match(re) != null){
a++;
}
}
return a;
}, 0);
console.log(result);

MyArray = [{
fruit1: "Orange is blabla",
fruit2: "Apple blabla",
fruit3: "blabla Banana",
color1: "ORANGE"
}, {
fruit4: "blabla Orange",
fruit5: "Apple",
fruit6: "Banana",
color2: "orange blabla"
}];
var totalOrange = 0;
MyArray.map(function(item) {
for (var key in item) {
if (item[key].toLowerCase().indexOf('orange') >= 0) {
totalOrange++;
}
}
});
console.log(totalOrange);

I guess something like this might work.
You could do it in one big loop to make it slightly faster, but this form in more readable imho.
const amountOfOranges = MyArray
// transform each object into an array of its values
.map( Object.values )
// remove all values not named 'orange'
.map( ary => ary.filter( value => value === 'orange' ) )
// replace all arrays by their length
.map( ary => ary.length )
// sum the results
.reduce( ( x, y ) => x + y, 0 );

var MyArray = [{fruit1:"Orange", fruit2:"Apple", fruit3:"Banana", color1:"ORANGE"},{fruit4:"Orange", fruit5:"Apple", fruit6:"Banana", color2:"orange"}];
var count = 0;
MyArray.map(function(item,index){
Object.keys(item).map(function(key){
if(item[key].toLowerCase().indexOf('orange') >= 0){
count++;
}
});
});
console.log(count);

With ES6 you can use spread syntax ... and Object.values to do this.
var MyArray = [{ fruit1: "Orange is blabla", fruit2: "Apple blabla", fruit3: "blabla Banana", color1: "ORANGE" }, { fruit4: "blabla Orange", fruit5: "Apple", fruit6: "Banana", color2: "orange blabla" }]
var count = [].concat(...MyArray.map(Object.values))
.filter(e => e.toLowerCase().includes('orange'))
.length;
console.log(count)

You can do something like this : -
const count = MyArray.reduce((count,item)=>{
Object.keys(item).forEach((val)=>{
if(item[val].toLowerCase().indexOf('orange') != -1){
count++;
}
})
return count
},0)

Related

Fastest way to loop over 2 mixed arrays and return the matching value on intersection

I'm trying to create a JavaScript method which loops over 2 arrays and returns an array of the matched value.
My a1 parameter in the 'getMatchedArray' method is an array of strings and objects, while arr2 is always array of objects.
However, a2 parameter in the 'getMatchedArray' method is an array that can contain an object with value property or without value property as seen in the sample arrays used.
I'm very close to it but somehow not able to figure out, what is the mistake I'm making?
Is there a faster way using intersection to achieve this?
const arr1 = ["red", {
"code": "red",
"label": "test"
}, {
"code": "blue",
"label": "test1"
}, "white", "blue", {
"code": "red",
"label": "test2"
}];
const arr2 = [{
"code": "red",
"value": "test2"
}];
const arr3 = [{
"code": "blue"
}];
const arr4 = [{
"code": "red",
"value": "test3"
}]
function getMatchedArray(a1, a2) {
return a1.reduce((memo, opt) => {
const isOptionFound = a2.some(obj => {
if (obj.value) {
return obj.value === opt.label;
} else {
return !opt.code && opt === obj.code;
}
});
if (isOptionFound) {
memo.push(opt);
}
return memo;
}, []);
}
const result1 = getMatchedArray(arr1, arr2);
const result2 = getMatchedArray(arr1, arr3);
const result3 = getMatchedArray(arr1, arr4);
console.log(result1);
console.log(result2);
console.log(result3);
Expected output:
result1:
[{
"code": "red",
"label": "test2"
}]
result2: ["blue"]
result3: ["red"]
result1, result 2 are fine, but my result3 is incorrect.
Any help on this?
//Try this
function findMatchingValues(arr1, arr2) {
const hashTable = {};
const matchingValues = [];
// Populate hash table with values from arr1
for (let i = 0; i < arr1.length; i++) {
const val = arr1[i];
hashTable[val] = true;
}
// Check arr2 for matching values
for (let i = 0; i < arr2.length; i++) {
const val = arr2[i];
if (hashTable[val]) {
matchingValues.push(val);
}
}
return matchingValues;
}
You can also achieve this requirement by separating the string and object elements from an array and then applied filter on those arrays based on the passed 2nd parameter in the function by stringify the passed parameters in the function.
Live Demo :
const arr1 = ["red", {
"code": "red",
"label": "test"
}, {
"code": "blue",
"label": "test1"
}, "white", "blue", {
"code": "red",
"label": "test2"
}];
const arr2 = [{
"code": "red",
"value": "test2"
}];
const arr3 = [{
"code": "blue"
}];
const arr4 = [{
"code": "red",
"value": "test3"
}];
function getMatchedArray(a1, a2) {
let strA2 = JSON.stringify(a2);
const strArrayFromA1 = a1.filter(item => typeof item === 'string');
const objArrayFromA1 = a1.filter(item => typeof item === 'object');
const matchedObject = objArrayFromA1.filter(elem => {
strA2 = strA2.replaceAll('value', 'label');
return strA2.includes(JSON.stringify(elem));
});
const matchedString = strArrayFromA1.filter(elem => strA2.includes(elem));
return matchedObject.length ? matchedObject : matchedString.length ? matchedString : 'No match found.';
}
const result1 = getMatchedArray(arr1, arr2);
const result2 = getMatchedArray(arr1, arr3);
const result3 = getMatchedArray(arr1, arr4);
console.log(result1);
console.log(result2);
console.log(result3);
The issue with the third result is that the expected output is an array of objects with the matching values, but the current implementation is returning a single object. To fix this, you can modify the function to push the opt value to memo instead of the opt object when there is a match in the arr4.
Here is the modified function:
function getMatchedArray(a1, a2) {
return a1.reduce((memo, opt) => {
const isOptionFound = a2.some(obj => {
if (obj.value) {
return obj.value === opt.label;
} else {
return !opt.code && opt === obj.code;
}
});
if (isOptionFound) {
memo.push(opt.label || opt);
}
return memo;
}, []);
}
With this modification, the output for result3 will be ["red"], which is the expected result.
Regarding the second part of the question, there is a faster way to achieve this using the filter and includes array methods. Here is an example implementation:
function getMatchedArray(a1, a2) {
return a1.filter(opt => {
return a2.some(obj => {
if (obj.value) {
return obj.value === opt.label;
} else {
return opt.code && obj.code && opt.code === obj.code;
}
});
});
}
This implementation uses filter to create a new array with all the elements that match the condition, and includes to check if the a2 array includes the opt value.

filter array and return the object containing the closest strings inside array inside an object, inside another array

I want to return the object containing the closest strings inside array inside an object, inside another array,
my indexOf() only return the exact string as true.
I tried replacing indexOf() with march(), matches(), includes() nothing works.
Please advice
let SellerList = [
{ supplyList: ["apple", "orange", "red apple"] },
{ supplyList: ["apple juice", "drink", "green apple", "dream app"] },
{ supplyList: ["lamp", "dog", "cat", "man"] }
];
let stringToMatch = "app";
let filteredList = SellerList.filter(
(txt) => txt.supplyList.indexOf(stringToMatch) !== -1
);
the output i wish for is all the objects containing the closest strings for example:
[
{ supplyList: ["apple", "orange", "red apple"] },
{ supplyList: ["apple juice", "drink", "green apple", "dream app"] }
];
You have an array inside an object, inside another array, so you want to target that inner array and call filter on it:
let SellerList = [{
supplyList: ['apple', 'orange', 'red apple']
}];
let stringToMatch = 'app';
let filteredList = SellerList[0].supplyList.filter(txt => txt.indexOf(stringToMatch) !== -1);
console.log(filteredList)
Please try the following solution
let SellerList = [
{ supplyList: ["apple", "orange", "red apple"] },
{ supplyList: ["apple juice", "drink", "green apple", "dream app"] },
{ supplyList: ["lamp", "dog", "cat", "man"] },
];
let stringToMatch = "app";
let filteredList = SellerList.reduce((previousValue, currentValue) => {
if (currentValue.supplyList.join().includes(stringToMatch)) {
previousValue = [...previousValue, { supplyList: currentValue.supplyList }];
}
return previousValue;
}, []);
console.log(filteredList);
See
Array.prototype.reduce()
Array.prototype.join()
You should try to match the inner strings of the supplyLists instead of the arrays themselves.
let SellerList = [
{ supplyList: ['apple','orange','red apple'] },
{ supplyList: ['apple juice','drink','green apple'] }
];
let stringToMatch = 'app';
let filteredList = SellerList.map(list => {
return list.supplyList.filter(item => {
return item.indexOf(stringToMatch) >= 0
})
});
console.log(filteredList);

JavaScript: Reduce an array to nested objects

So suppose my array looks like this:
let langArr = [
["python", "blue"]
,["python", "blue"]
,["c++", "red"]
,["java", "yellow"]
,["javascript", "lime"]
,["shell", "green"]
,["c++", "red"]
];
what I want is something like this:
{
python: {
count: 2
color: "blue"
}
c++: {
count: 2
color: "red"
}
java: {
count: 1
color: "yellow"
}
and so on...
}
I tried reduce method like this:
let langCount = langArr.reduce((lang, [name, color]) => {
lang[name] = (lang[name] || 0) + 1;
lang[color] = 'color';
return lang;
}, {});
console.log(langCount);
but I get this output:
{
python: 2
blue: "color"
c++: 2
red: "color"
java: 1
yellow: "color"
and so on...
}
You need an object for each language.
This approach takes an object as default value if lang[name] is falsy, like undefined.
The pattern
variable = variable || value;
works with a logical OR ||:
if variable has a truthy value, take this value,
if variable has a falsy value, take value instead.
let langArr = [["python", "blue"], ["python", "blue"], ["c++", "red"], ["java", "yellow"], ["javascript", "lime"], ["shell", "green"], ["c++", "red"]],
langCount = langArr.reduce((lang, [name, color]) => {
lang[name] = lang[name] || { count: 0, color };
lang[name].count++;
return lang;
}, {});
console.log(langCount);
You can use this:
array.reduce((acc, current) => {
if(!acc.hasOwnProperty(current[0])){
acc[current[0]] = {count: 0, color: current[1]};
}
acc[current[0]].count += 1;
return acc;
}, {});

Categorize object in JavaScript loop

I have the following object:
var object = [
{
"category": "Apple",
"color": "green"
},
{
"category": "Orange",
"color": "Orange"
},
{
"category": "Apple",
"color": "green"
}
];
I am trying to iterate the data via category, so the following would show in a list:
Apple
Apple
Orange
Below is the code I've tried but unfortuantely it shows in the order it appears in the object. Any ideas would be much appreciated.
function makeUL(object) {
var list = document.createElement('ul');
for(var i = 0; i < object.length; i++) {
var item = document.createElement('li');
var a = document.createElement("a");
a.textContent = object[i].category;
a.setAttribute('href', 'http://test');
item.appendChild(a);
list.appendChild(item);
}
return list;
}
A solution with group change:
var object = [{ "category": "Apple", "color": "green" }, { "category": "Orange", "color": "Orange" }, { "category": "Apple", "color": "green" }];
function makeUL(object) {
var div = document.createElement('div');
object.sort(function (a, b) { return a.category.localeCompare(b.category); });
object.forEach(function (aa) {
var a = document.createElement("a"),
item = document.createElement('li'),
p;
if (aa.category !== this.last) {
p = document.createElement('p');
p.innerHTML = aa.category;
div.appendChild(p);
this.list = document.createElement('ul');
div.appendChild(this.list);
this.last = aa.category;
}
a.textContent = aa.category;
a.setAttribute('href', 'http://test');
item.appendChild(a);
this.list.appendChild(item);
}, { last: undefined, list: undefined });
return div;
}
document.body.appendChild(makeUL(object));
You could use Array.sort
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
function compare(a, b) {
if (a is less than b by some ordering criterion) {
return -1;
}
if (a is greater than b by the ordering criterion) {
return 1;
}
// a must be equal to b
return 0;
}
sort the array before using it in for loop
object.sort(function(a,b){
return a.category > b.category
});
object.sort(function(a, b) {
return a.category > b.category;
});
Result
[ { category: 'Apple', color: 'green' },
{ category: 'Apple', color: 'green' },
{ category: 'Orange', color: 'Orange' } ]
If you want your array to be sorted alphabetically ( DESC order, from A to Z ) you have to call the .sort() method first
function makeUL(object) {
var list = document.createElement('ul');
object.sort();
for(var i = 0; i < object.length; i++) {
var item = document.createElement('li');
var a = document.createElement("a");
while(i<length - 1 && object[i].category == object[i+1].category)
a.textContent += object[i].color + ", ";
a.setAttribute('href', 'http://test');
item.appendChild(a);
list.appendChild(item);
}
return list;
}

Convert strings in array to objects

I am receiving an array of strings from a server in the following format:
var fruitsStrings = ["apple", "banana", "orange" ];
Is it possible to convert this into an array of objects, like below?
var fruitsObjects = [
{
fruit: "apple"
},
{
fruit: "banana"
},
{
fruit: "orange"
}
];
All the object properties will be the same. Happy to use pure JavaScript or jQuery. I've tried using jquery.extend but as this adds unique IDs before each value it's not really fit for my purpose.
Thank you.
you can use .map
var fruitsStrings = ["apple", "banana", "orange" ];
var fruitsObjects = fruitsStrings.map(function( val, i ) {
return {fruit:val};
});
document.write(JSON.stringify(fruitsObjects));
var fruitsStrings = ["apple", "banana", "orange" ];
var fruitsObjects = fruitsStrings.map(function( val, i ) {
return {fruit:val};
});
document.write(JSON.stringify(fruitsObjects));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
var fruitsStrings = ["apple", "banana", "orange" ];
var fruitsObjects = [];
fruitsStrings.forEach(function (item) {
fruitsObjects.push({ fruit: item });
});
Working demo.
Try this:
var fruitsStrings = ["apple", "banana", "orange" ];
var fruitsObjects = [];
$.map( fruitsStrings, function( val, i ) {
fruitsObjects.push({ fruits: val });
});
A simple Array.prototype.map will do:
var fruitsStrings = ["apple", "banana", "orange"],
fruitsArray = fruitsStrings.map(function (a) { return { fruit: a } });
document.write('<pre>' + JSON.stringify(fruitsArray, 0, 4) + '</pre>');
You could also use this function where you can specify the key.
function toObjects(key,arr) {
var objects = [];
for (var i = 0; i < arr.length; ++i){
var obj = {};
obj[key] = arr[i];
objects[i] = obj;
}
return objects;
}
var fruitsStrings = ["apple", "banana", "orange" ];
toObjects('fruit',fruitsStrings);
// [{fruit: "apple"},{fruit: "banana"},{fruit: "orange"}]
Try this:
var fruitsStrings = ["apple", "banana", "orange" ];
var fruitsObjects = [];
fruitsStrings.map(function(v,i){
fruitsObjects.push({'fruit':v});
});
console.log(fruitsObjects);
Working Demo

Categories