javascript, json value counting? - javascript

I want to count value's number.
Here is json.
x = {"first" : ["apple", "banana", "car", "day"],
"second" : ["apple","car"],
"third" : ["day"],
"fourth" " [],
"fifth" : ["apple"]
}
And I need these output.
object..???['apple']
>>>3
object..???['banana']
>>>1
object..???['car']
>>>2
object..???['day']
>>>2
object..???['elephant']
>>>0
What kind of code should I use?
I tried the following but it isn't working:
Object.values(x['day']).length;

You can get all the values in your object and put them into an array using Object.values() and .flat(). Then, you can .filter() out any items in your values array which are not your desired item. Finally, you can get the .length of this array to find how many items matched your search.
See example below:
const x = {
"first": ["apple", "banana", "car", "day"],
"second": ["apple", "car"],
"third": ["day"],
"fourth": [],
"fifth": ["apple"]
}
const countItem = (obj, search) =>
Object.values(obj).flat().filter(item => item === search).length;
console.log(countItem(x, "apple")); // 3
console.log(countItem(x, "banana")); // 1
console.log(countItem(x, "car")); // 2
console.log(countItem(x, "day")); // 2
console.log(countItem(x, "elephant")); // 0

Use flat() to flatten out the object's values and then use a reduce operation to calculate the number of times the key appears in the object:
const x = {
"first": ["apple", "banana", "car", "day"],
"second": ["apple", "car"],
"third": ["day"],
"fourth": [],
"fifth": ["apple"]
};
const count = (k) => Object.values(x).flat().reduce((a, v) => a + (k === v ? 1 : 0), 0);
console.log(count('day')); // 2

Related

Counting occurrences and frequency of elements in an array and sort them

I have input array as follows. I want to get the unique occurrences name and frequency of those occurrences. I am able to achieve that as shown below.
let input = ["apple", "orange" , "pear", "orange", "apple", "orange"];
input.reduce(function (acc, curr) {
return acc[curr] ? ++acc[curr] : acc[curr] = 1, acc
}, {});
Result:
{ "apple": 2, "orange": 3, "pear": 1}
But I am expecting the result to be in ascending order of frequencies as shown below. Can someone let me know how to achieve it. Also, I have used function above. Can someone let me know how to use it with arrow operator (ES8 feature)
Expected Result:
{ "orange": 3, "apple": 2, "pear": 1 }
You can convert the unsorted object, which is not sortable, to an array, which is sortable, and then back to an object:
let input = ["apple", "orange" , "pear", "orange", "apple", "orange"];
const unsorted = input.reduce(function (acc, curr) {
return acc[curr] ? ++acc[curr] : acc[curr] = 1, acc
}, {});
const sorted = Object.entries(unsorted) // converts to array of key/value pairs
.sort(([,a],[,b]) => b - a) // sort descending (switch a and b to sort in reverse order)
.reduce((r, [k, v]) => ({ ...r, [k]: v }), {}); // reduce back to object
console.log(sorted)

How to create json object out of two arrays [duplicate]

This question already has answers here:
Create an object from an array of keys and an array of values
(9 answers)
Create object from two arrays
(4 answers)
Closed 2 years ago.
Having two arrays:
let values = ["52", "71", "3", "45", "20", "12", "634", "21"];
let names = ["apple", "orange", "strawberry", "banana", "coconut", "pineapple", "watermelon", "plum"];
How can I create an object like:
{
"apple": 52,
"orange": 71,
"strawberry": 3,
"banana": 45,
"coconut": 20,
"pineapple": 12,
"watermelon": 634,
"plum": 21
}
I tried using Object.assign but this only overrides the values.
Object.assign<any, any>(names, values);
Object.defineProperties doesn't work as well or - more likely - I don't know how to use them.
EDIT
I tried the
let temp = {};
names.forEach((item, index) => {
console.log('item: ', item);
console.log('index: ', index);
console.log('temp[item]: ', temp[item]);
console.log('values[index]: ', values[index]);
temp[item] = values[index];
console.log(names);
});
but this is what I got
Create a new result-object. Add to this object foreach element of names a nnew object with name and corresponding value.
Edited: Because it seems tht you have in your values-array all elements as string and in your result-object the values are integers I use parseInt for convertion.
Note: Using a variable name is not so good because you get an TypeError if you want to use anything like this name.forEach, name.map. It seems it's a reserved word or something like this.
let values = ["52", "71", "3", "45", "20", "12", "634", "21"];
let names = ["apple", "orange", "strawberry", "banana", "coconut", "pineapple", "watermelon", "plum"];
let temp = {};
names.forEach((elem, index) => { temp[elem]=parseInt(values[index]) });
names.forEach((item, index) => {
console.log('item: ', item);
console.log('index: ', index);
console.log('temp[item]: ', temp[item]);
console.log('values[index]: ', values[index]);
temp[item] = values[index];
console.log(names);
});

react javascript - json how to merge multiple array elements into one string

I have a JSON response as below:
[{
"id": 1,
"food": {
"fruits": ["Banana", "Orange", "Apple", "Mango"],
"veggies": ["greens", "peppers", "carrot", "potatoes"],
}
},
{
"id": 2,
"food": {
"fruits": ["grapes", "berries", "peach", "pears"],
"veggies": ["cabbage", "spinach"],
"dairy": ["nutmilk", "goatmilk"]
}
}
]
Now i want to merge the Arrays each "id" (1,2 in example) into string ( ; delimited) like below:
id_1 = Banana;Orange;Apple;Mango;greens;peppers;carrot;potatoes
// observer "id_2" has additional array - "dairy"
id_2 = grapes;berries;peach;pears;cabbage;spinach;nutmilk;goatmilk
The key's are dynamic so for some records there are 2 arrays and for some records it can be 3 or 4 and may be 1.
I tried using react/Java Script Array.concat(), but i am not sure how to do it dynamically. Please help me. Thank you.
This is doable easily using Object.values().flat().join(';') demonstrated below:
let arr=[{"id":1,"food":{"fruits":["Banana","Orange","Apple","Mango"],"veggies":["greens","peppers","carrot","potatoes"],}},{"id":2,"food":{"fruits":["grapes","berries","peach","pears"],"veggies":["cabbage","spinach"],"dairy":["nutmilk","goatmilk"]}}];
const result = arr.map(({id,food}) => ({id, food: Object.values(food).flat().join(';')}));
console.log(result);
You may easily restructure the output by simply changing it to e.g. ["id_"+id]: Object.values(...)
First flatten using map, flat and join. Then convert the resulting array of objects to a single object using assign.
var db = [{"id": 1,"food": {"fruits": ["Banana", "Orange", "Apple", "Mango"], "veggies": ["greens","peppers","carrot","potatoes"], }},{"id" : 2,"food": {"fruits": ["grapes", "berries", "peach", "pears" ], "veggies": ["cabbage","spinach"], "dairy": ["nutmilk","goatmilk"]}}];
var flat = db.map(
({id, food}) => ({[`id_${id}`]: Object.values(food).flat().join(';')})
);
var result = Object.assign(...flat);
console.log(result);
This is really two problems: looping through an array of objects to combine them into one object, and looping through an object to concat all of its array.
Tackling the second one first, something like this would work:
const concatArraysInObject = obj =>
Object.values(obj).reduce((result, arr) => result.concat(arr), []);
const input = { a: [1,2,3], b: [4,5,6], c: [7,8,9] };
const output = concatArraysInObject(input);
console.log(output);
Object.values() will give you an array of all arrays in an object.
The reduce() function takes a two parameters: a function and initial value.
The function should also take (at least) 2 parameters: the result of the last call (or initial value) and the current value in the array.
It'll call the function once for each element in the array.
Now, with that solved, we can tackle the first problem.
For this, we can also use reduce() as well, and we'll construct our combined object on each call.
const concatArraysInObject = (obj) =>
Object.values(obj).reduce((result, arr) => result.concat(arr), []);
const mergeObjectsInArray = (arr, dataKey) =>
arr.reduce((result, obj) => ({ ...result, [obj.id]: concatArraysInObject(obj[dataKey]) }), {});
const input = [
{ id: 'A', data: { a: [1,2,3], b: [4,5,6] } },
{ id: 'B', data: { c: [7,8,9], d: [10,11,12] } }
];
const output = mergeObjectsInArray(input, 'data');
console.log(output);
An important note of warning: object key order is NOT guaranteed in JavaScript. While 99% of the time they will be in the order you expect, this is not a guarantee, so if you depend on the order of the keys for the order of the array (if order matters), you'll want to change your input structure. If order doesn't matter, it is probably fine how it is.
Try this using basic for loop. Inside you will compute key dynamically and value being flattened array of Object.values of the iterating object.
var input = [{
id: 1,
food: {
fruits: ["Banana", "Orange", "Apple", "Mango"],
veggies: ["greens", "peppers", "carrot", "potatoes"]
}
},
{
id: 2,
food: {
fruits: ["grapes", "berries", "peach", "pears"],
veggies: ["cabbage", "spinach"],
dairy: ["nutmilk", "goatmilk"]
}
}
];
var temp = [];
for (var i = 0; i < input.length; i++) {
temp.push({
[`id_${input[i].id}`]: Object.values(input[i].food)
.flat(1)
.join(";")
});
}
console.log(temp); // this gives you an array
console.log(Object.assign(...temp));// in case you require one single object

removing array javascript value sequentially from first index

I have this array :
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
and I want to remove array value sequentially from first index.
so it will produce:
[ "apple", "orange", "watermelon", "blueberry", "lemon", "guava" ]
[ "orange", "watermelon", "blueberry", "lemon", "guava" ]
[ "watermelon", "blueberry", "lemon", "guava" ]
[ "blueberry", "lemon", "guava" ]
[ "lemon", "guava" ]
[ "guava" ]
I've already tried this code:
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
runLoop = async () => {
for(const item of items){
await new Promise( resolve => setTimeout( resolve, 1000 ));
console.log(items);
remove(items, item);
console.log('------------');
}
}
function remove(array, element) {
console.log('deleting '+element);
const index = array.indexOf(element);
array.splice(index, 1);
}
but the result it's not what I expected,
here is the result:
Array(6) [ "apple", "orange", "watermelon", "blueberry", "lemon", "guava" ]
Array(5) [ "orange", "watermelon", "blueberry", "lemon", "guava" ]
Array(4) [ "orange", "blueberry", "lemon", "guava" ]
The problem is that array iterable is live - if you invoke the iterator with for..of and mutate the array while that iterator is still being used, the resulting items iterated over will likely be unintuitive - some indicies may be missed. It's kind of like what's going on here:
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
for (let i = 0; i < items.length; i++) {
console.log('item: ', items[i]);
items.splice(i, 1);
}
The loop only runs 3 times, because you're removing items from the array while you're iterating over it, so some indicies get skipped.
One possibility is to make a copy of the array first, when invoking the iterator with for..of, so that the iterator will always iterate over every item that was in the original array sequentially:
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
runLoop = async () => {
for(const item of items.slice()){
await new Promise( resolve => setTimeout( resolve, 300 ));
console.log(items);
remove(items, item);
console.log('------------');
}
}
function remove(array, element) {
console.log('deleting '+element);
const index = array.indexOf(element);
array.splice(index, 1);
}
runLoop();
You need to splice at index zero,
array.splice(0, 1);
or just shift the first element.
array.shift();
An alternative can a recursive function and shift which removes the first element from an array
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
function removeElem(arr) {
if (arr.length !== 1) {
console.log(arr)
arr.shift();
removeElem(arr)
} else {
console.log(arr)
}
}
removeElem(items)
You can use Array.slice to achieve this. When using splice, remember that it will affect the original array, which should not be done according to the functional approach of javascript. Functional programming doesn't recommend to mutate the original object.
let items = ["apple", "orange", "watermelon", "blueberry", "lemon", "guava"];
for(let i=0;i<items.length;i++){
console.log(items.slice(i,items.length));
}

Count number of times a string is repeated in array using Lodash

I have an array of strings which are tags of blog posts from database.
This is the example end result of a query :
["apple","banana", "apple", "orange","grapes","mango","banana"];
I need to know how many times a string is repeated in that array so I can build a sort of tag cloud.
Final end result should look like: [{name:"apple",count:2}, {name:"banana", count:2}, {name: "orange",count:1} ...];
I am using lodash in my project and would like to use it if possible. plain javascript is also fine.
You can use groupBy to do the heavy lifting then use map to format the result to your liking:
const data = ["apple", "banana", "apple", "orange", "grapes", "mango", "banana"];
const result = _.values(_.groupBy(data)).map(d => ({name: d[0], count: d.length}));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Use reduce and map
var input = ["apple","banana", "apple", "orange","grapes","mango","banana"];
var map = input.reduce( (a,c) => ( a[c] = a[c] || 0, a[c]++, a ) ,{});
var output = Object.keys( map ).map( s => ({name: s, count:map[s]}) );
Demo
var input = ["apple", "banana", "apple", "orange", "grapes", "mango", "banana"];
var map = input.reduce((a, c) => (a[c] = a[c] || 0, a[c]++, a), {});
var output = Object.keys(map).map(s => ({
name: s,
count: map[s]
}));
console.log(output);
Create a map, mapping name to count. Loop over the list, for each item, if its' in the map, increment it's count, else set its count to one.
if (tag in map) { map[tag] += 1 }
else { map[tag] = 1 }
Then you can iterate of the map and convert it to a list of objects.
To count use _.countBy(), then transform to requested form, by using _.entries(), and mapping the tuples to objects:
const data = ["apple", "banana", "apple", "orange", "grapes", "mango", "banana"];
const result = _.entries(_.countBy(data)).map(([name, count]) => ({ name, count }));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Categories

Resources