Update the count value in an array - javascript

I have two array of objects arr 1 and arr 2
arr1 = [{fruit: 'apple',count: 0}] arr2 = [{fruit: 'apple',count: 0}]
Need to create the function which accepts arr1 and arr2 as arguments and compare the fruit name if its same need to update the count value based on the count input else push the value to the array
sample output 1:
Inputs:
arr1 = [{fruit: 'apple',count: 10}] arr2 = [{fruit: 'apple',count: 30},{fruit: 'orange',count: 20}]
Output:
[{fruit: 'apple',count: 40},{fruit: 'orange',count: 20}]
sample output2
Inputs:
arr1 = [{fruit: 'apple',count: 15}] arr2 = [{fruit: 'orange',count: 20}]
Output:
[{fruit: 'apple',count: 15},{fruit: 'orange',count: 20}]
code that i have tried:
function compareAndUpdateCount(arr1, arr2) {
for (i = 0; i < arr1.length; i++) {
if (arr1[i].fruit === arr2[i].fruit) {
arr1[i].count = arr1[i].count + arr2[i].count;
} else {
arr1.push(arr2[i])
}
}
}
This works fine when the array lengths are same ,if its different need help on writing the optimise code and also the reduce time complexity if we have more data

You will need a setter for count in your class
Make a new array of objects temparr
temparr[0] = arr1[0];
if((arr1[0].fruit).equals(arr2[0].fruit)) {
temparr[0].setcount(arr1[0].count+arr2[0].count);
}
else {
temparr[1]=arr2[0];
}
At the end u print temparr

You can easily achieve the result using Map and reduce
function groupObject(arr1, arr2) {
const map = new Map();
const temp = [...arr1, ...arr2].reduce((acc, { fruit, count }) => {
map.has(fruit)
? (map.get(fruit).count = map.get(fruit).count + count)
: map.set(fruit, { fruit, count });
return acc;
}, map);
return [...map.values()];
}
const arr1 = [{ fruit: "apple", count: 15 }];
const arr2 = [{ fruit: "orange", count: 20 }];
console.log(groupObject(arr1, arr2));
const arr3 = [{ fruit: "apple", count: 0 }];
const arr4 = [{ fruit: "apple", count: 0 }];
console.log(groupObject(arr3, arr4));
/* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }

var result;
if(arr1.length < 1) {
result = arr2;
} else if(arr2.length < 1) {
result = arr1;
} else {
var existing = [];
var arr3 = [];
arr1.forEach(function (item, index) {
arr2.forEach(function (item2, index2) {
if(item.fruit === item2.fruit) {
item.count = item.count + item2.count;
existing.push(index2);
} else {
arr3.push(item);
if(!existing.includes(index2)) {
arr3.push(item2);
}
}
});
});
result = arr3;
}

Loop within another loop to compare all object properties and then use an if statement to sum up the counter and remove the item of the second array using splice()
Try the following snippet:
var arr1 = [{fruit: 'apple',count: 10}];
var arr2 = [{fruit: 'apple',count: 30}, {fruit: 'orange',count: 20}, {fruit: 'apple',count: 20}, {fruit: 'banana',count: 20}];
var counter = 0;
for(obj1 in arr1){
for(obj2 in arr2){
if (arr1[obj1].fruit === arr2[obj2].fruit) {
arr1[obj1].count = arr1[obj1].count + arr2[obj2].count;
arr2.splice(counter, 1);
counter++;
}
}
}
arr1 = arr1.concat(arr2);
console.log(arr1)

Try using reduce to group the fruits along with its count, followed by a simple map to get the required array
const arr1 = [{fruit: 'apple',count: 10}] , arr2 = [{fruit: 'apple',count: 30},{fruit: 'orange',count: 20}]
const res = [...arr1, ...arr2].reduce((acc, curr) => {
acc[curr.fruit]
? (acc[curr.fruit].count += curr.count)
: (acc[curr.fruit] = curr);
return acc;
}, {});
console.log(Object.keys(res).map((item) => res[item]));

Related

How to split an array into smaller arrays every time a specific value appears JavaScript?

How would you go about splitting an array at the word 'split' and creating smaller sub arrays out of them?
This is what my array looks like right now (but much longer):
const myArray = ['abc', 'xyz', 123, 'split', 'efg', 'hij', 456, 'split'];
This is what I would like it to look like:
const newArray =[['abc', 'xyz', 123], ['efg', 'hij', 456]];
If it helps at all I also have the indexes of the words 'split' in an array like this:
const splitIndex = [3, 7];
You could iterate splitIndex and slice the array until this index.
const
data = ['abc', 'xyz', 123, 'split', 'efg', 'hij', 456, 'split'],
splitIndex = [3, 7],
result = [];
let i = 0;
for (const j of splitIndex) {
result.push(data.slice(i, j));
i = j + 1;
}
console.log(result);
const myArr = ['abc', 'xyz', 123, 'split', 'efg', 'hij', 456, 'split'];
const foo = (arr, key) => {
let temp = [];
const result = [];
arr.forEach(v => {
if (v !== key) {
temp.push(v);
} else {
result.push(temp);
temp = [];
}
})
return result;
}
console.log(foo(myArr, 'split'));
output:
[ [ 'abc', 'xyz', 123 ], [ 'efg', 'hij', 456 ] ]

Find Index where Two Arrays have same Value

If I have two arrays, in Javascript:
let arr1 = ["Dog", "Cat", "Monkey", "Zebra", "Goat", "Goose"];
let arr2 = ["Zebra", "Goat"];
How can I find the indexes of the larger array where there is a match and store them in another array so example output would be:
let indexes = [3,4]
You could do it by mapping over your search-teams (arr2) and then using the findIndex Method on the source-array (arr1) like this:
let arr1 = ["Dog", "Cat", "Monkey", "Zebra", "Goat", "Goose"];
let arr2 = ["Zebra", "Goat"];
const result = arr2.map(searchTerm => arr1.findIndex((compareTerm) => compareTerm === searchTerm));
console.log(result);
You can achieve the expected output using Array.map and Array.findIndex
let arr1 = ["Dog", "Cat", "Monkey", "Zebra", "Goat", "Goose"];
let arr2 = ["Zebra", "Goat"];
const findIndexes = (param1, param2) => {
let arr1 = [...param1];
let arr2 = [...param2];
//swap the arrays if the no.of array elements
//in the second array are greater than first
if(arr1.length < arr2.length) {
[arr1, arr2] = [arr2, arr1];
}
//Loop through all the items of the smaller array
//check if the element is present in the bigger array
return arr2.map(a2 => arr1.findIndex(a1 => a1 === a2));
}
console.log(findIndexes(arr1, arr2));
//here for "test", we'll get index as -1, because
//if the matching element is not found, findIndex will
//return -1
let arr3 = ["Cat", "Goose", "test"];
console.log(findIndexes(arr3, arr1));
If you wish to get the indexes of the elements that are found and wish to filter out all the -1s, below is the code for the same.
let arr1 = ["Dog", "Cat", "Monkey", "Zebra", "Goat", "Goose"];
let arr2 = ["Zebra", "Goat"];
const findIndexes = (param1, param2) => {
let arr1 = [...param1];
let arr2 = [...param2];
if(arr1.length < arr2.length) {
[arr1, arr2] = [arr2, arr1];
}
return arr2.map(a2 => arr1.findIndex(a1 => a1 === a2)).filter(ele => ele !== -1);
}
console.log(findIndexes(arr1, arr2));
let arr3 = ["Cat", "Goose", "test"];
console.log(findIndexes(arr3, arr1));
let arr1 = ["Dog", "Cat", "Monkey", "Zebra", "Goat", "Goose"];
let arr2 = ["Zebra", "Goat"];
let indexes = []
arr1.forEach((item, index) => {
if(arr2.includes(item)){
indexes.push(index)
}
})
console.log(indexes)

Return a new array of objects with same values grouped by qauntity/length

So i currently have an array like this:
const allMeats = ['Bacon','Bacon','Bacon', 'Steak', 'Lettuce', 'Cabbage','Cabbage','Cabbage','Steak', 'Veal']
I would like to morph the array so that it becomes an array of objects with key/vals that determine the value of the duplicates.
Currently i have got
const meatsGrouped = allMeats.reduce(
(acum, cur) => Object.assign(acum, { [cur]: (acum[cur] || 0) + 1 }),
[],
);
however this code turns the array int this:
[Bacon: 3, Steak: 2, Lettuce: 1, Cabbage: 3, Veal: 1]
when ideally i want it to look like this:
[{Bacon: 3}, {Steak: 2}, {Lettuce: 1}, {Cabbage: 3}, {Veal: 1}]
Can any1 please tell me what i'm doing wrong/missing?
You could do it using reduce and map method.
const allMeats = [
'Bacon',
'Bacon',
'Bacon',
'Steak',
'Lettuce',
'Cabbage',
'Cabbage',
'Cabbage',
'Steak',
'Veal',
];
const ret = Object.entries(
allMeats.reduce((prev, c) => {
const p = prev;
const key = c;
p[key] = p[key] ?? 0;
p[key] += 1;
return p;
}, {})
).map(([x, y]) => ({ [x]: y }));
console.log(ret);
You can do the following using reduce method,
let allMeats = ['Bacon','Bacon','Bacon', 'Steak', 'Lettuce', 'Cabbage','Cabbage','Cabbage','Steak', 'Veal'];
let res = allMeats.reduce((prev, curr) => {
const index = prev.findIndex(item => item.hasOwnProperty(curr));
if(index > -1) {
prev[index][curr]++;
}else {
prev.push({[curr]: 1});
}
return prev;
}, []);
console.log(res);

Use object property values of two JS array of objects

I have two arrays
let arr1 = [{'id': 'ee', 'seat': '12'},
{'id': 'aa', 'seat': '8'}
]
let arr2 = [
{'id': 's22', 'num': ''},
{'id': '2s2', 'num': ''}
]
I want to copy seat values from arr1 to num property at arr2, but I only get last arr1 seat value in for loop.
for( let i = 0; i <= arr1.length; i++) {
for( let x = 0; x <= arr2.length; x++) {
arr2[x]['num'] = arr1[i]['seat'];
}
}
console.log(arr2);
Iterate arr2 with Array.forEach(), and take the respective seat value by index from arr1:
const arr1 = [{'id': 'ee', 'seat': '12'},{'id': 'aa', 'seat': '8'}]
const arr2 = [{'id': 's22', 'num': ''},{'id': '2s2', 'num': ''}]
arr2.forEach((o, i) => o.num = arr1[i].seat)
console.log(arr2)
You need just a single loop and check if the index of the array if is (only) smaller than the length of the minimum of both arrays.
If the index get the length of an array, the access returns undefined, because this element is not in the array.
A further access to a property of this throws an error:
Unable to get property 'seat' of undefined or null reference
var arr1 = [{ id: 'ee', seat: '12' }, { id: 'aa', seat: '8' }],
arr2 = [{ id: 's22', num: '' }, { id: '2s2', num: '' }],
i, l;
for (i = 0, l = Math.min(arr1.length, arr2.length); i < l; i++) {
arr2[i].num = arr1[i].seat;
}
console.log(arr2);
You can do it in just one for loop.
for(let i = 0; i < arr1.length; i++) {
arr2[i].num = arr1[i].seat;
}
Hope this helps!
Assuming you want to match indices, this should do it.
const arr1 = [
{'id': 'ee', 'seat': '12'},
{'id': 'aa', 'seat': '8'}
]
const arr2 = [
{'id': 's22', 'num': ''},
{'id': '2s2', 'num': ''}
]
const result = arr2.map((e, i) => ({...e, ...{num: arr1[i].seat}}))
console.log(result)
If you want all of the seats in each num, it wouldn't be much harder.

New array of objects, but with changed keys

I have a problem with picking some data with array of objects and pushing it into new object (in different array), but in different way.
const fruits = [
{name: "apple"},
{name: "kiwi"},
{name: "banana"},
{name: "orange"},
{name: "pineapple"},
{name: "coconut"},
{name: "peach"},
{name: "lemon"}
]
I want to pick a few items from this and paste them into completely new array, so it could look like this:
const manyFruits = [
{name: "apple-banana-kiwi-coconut"},
{name: "orange-pineapple-peach-lemon"}]
It would be great to do a function which takes an argument of how many fruits we want to pick into new array and they shouldn't repeat.
Below is my code. Firstly I create new array with names, then I push them into new array which depends on "length" and finally I try to create new array with objects, but it fails.
const fruitArray = length => {
const fruits = [
{name: "apple"},
{name: "kiwi"},
{name: "banana"},
{name: "orange"},
{name: "pineapple"},
{name: "coconut"},
{name: "peach"},
{name: "lemon"}
]
const allFruits = []
for (let i = 0; i < fruits.length; i++) {
allFruits.push(fruits[i].name)
}
const newFruits =[]
for (let i = 0; i < length; i++) {
newFruits.push(allFruits[i])
}
const manyFruitsInOneArr = []
for (let i = 0; i < 2; i++) {
let newArr = {
name: newFruits.join("-"),
}
manyFruitsInOneArr[i] = (newArr)
}
console.log(manyFruitsInOneArr)
}
fruitArray(2)
It generates new objects in new array, but items are the same all the time.
You can create function for this using for loop and inside map() method to get array of names and join() to make a string from values.
const fruits = [{"name":"apple"},{"name":"kiwi"},{"name":"banana"},{"name":"orange"},{"name":"pineapple"},{"name":"coconut"},{"name":"peach"},{"name":"lemon"}]
const pick = (arr, n) => {
const r = [];
for (var i = 0; i < arr.length; i += n) {
const name = arr
.slice(i, i + n)
.map(({name}) => name)
.join('-');
r.push({name})
}
return r;
}
const result = pick(fruits, 2)
console.log(result)
Update: to get names and sum of energy for each slice you can use map() and reduce() methods.
fruits = [ {name: "apple", energy: 100}, {name: "kiwi", energy: 126}, {name: "banana", energy: 150}, {name: "orange", energy: 118}, {name: "pineapple", energy: 98}, {name: "coconut", energy: 83}, {name: "peach", energy: 65}, {name: "lemon", energy: 36} ]
const pick = (arr, n) => {
const r = [];
for (var i = 0; i < arr.length; i += n) {
const slice = arr.slice(i, i+n);
const name = slice.map(({name}) => name).join('-')
const energy = slice.reduce((r, {energy}) => r + energy, 0);
r.push({name, energy})
}
return r;
}
const result = pick(fruits, 2)
console.log(result)
That could be done using recursion:
function subset(arr, n){
if(!(n - 1)) return [arr[0].name];
const result = [];
for(let i = 0; i < arr.length - n; i++){
for(const sub of subset(arr.slice(i + 1), n - 1)){
result.push(arr[i].name + "-" + sub);
}
}
return result;
}
So you can do:
subset(fruits, 5);

Categories

Resources