New array of objects, but with changed keys - javascript

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);

Related

Update the count value in an array

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]));

Making an exception when joining array's keys

I wanted to make an exception. It's hard for me to explain it, so let me show you what I mean.
My code:
fruits = [
{name: "apple", energy: 100, not: "kiwi"},
{name: "kiwi", energy: 126, not: "orange"},
{name: "banana", energy: 150, not: ""},
{name: "orange", energy: 118, not: "peach"},
{name: "pineapple", energy: 98, not: ""},
{name: "coconut", energy: 83, not: ""},
{name: "peach", energy: 65, not: ""},
{name: "lemon", energy: 36, not: ""}
]
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)
The result I get is
{name: "apple-kiwi", energy: 226},
{name: "banana-orange", energy: 268},
{name: "pineapple-coconut", energy: 181},
{name: "peach-lemon", energy: 101}
What I want is to make an exception (not in fruits). So apple shouldn't link with kiwi, kiwi with orange, etc. and it should look like this
{name: "apple-banana", energy: something},
{name: "kiwi-pineapple", energy: something},
...
I thought I could filter slice and check if any of it's items contains not, but I failed :(
Could anyone help me?
You need to take an array of names and an array of exceptions, and check them at the intersection:
fruits = [
{name: "apple", energy: 100, not: "kiwi"},
{name: "kiwi", energy: 126, not: "orange"},
{name: "banana", energy: 150, not: ""},
{name: "orange", energy: 118, not: "peach"},
{name: "pineapple", energy: 98, not: ""},
{name: "coconut", energy: 83, not: ""},
{name: "peach", energy: 65, not: ""},
{name: "lemon", energy: 36, not: ""}
]
function intersect (a1, a2) {
var isIntersect = false
a1.forEach(function (a) {
if (a.length > 0 && a2.indexOf(a) !== -1) isIntersect = true
})
return isIntersect
}
const pick = (arr, n) => {
const r = [];
for (var i = 0; i < arr.length; i += n) {
const slice = arr.slice(i, i+n);
const namesArr = slice.map(({name}) => name)
const notsArr = slice.map(({not}) => not)
if (!intersect(namesArr, notsArr)) {
const name = namesArr.join('-')
const energy = slice.reduce((r, {energy}) => r + energy, 0);
r.push({name, energy})
}
}
return r;
}
const result = pick(fruits, 2)
console.log(result)
Actually what you need is to filter the array to select the elements that doesn't have not property's value equal to the iterated item name:
const pick = (arr, n) => {
const r = [];
for (var i = 0; i < arr.length; i += n) {
var slice = [];
slice.push(arr[i]);
slice = slice.concat(arr.filter(function(x, ind) {
return x.name !== arr[i].name && x.not !== arr[i].name
}));
slice = slice.slice(0, n);
var name = slice.reduce((r, {
name
}) => r + name + "-", "");
name = name.replace(/\-$/, '');
const energy = slice.reduce((r, {
energy
}) => r + energy, 0);
r.push({
name,
energy
});
}
return r;
}
Demo:
var fruits = [{
name: "apple",
energy: 100,
not: "kiwi"
},
{
name: "kiwi",
energy: 126,
not: "orange"
},
{
name: "banana",
energy: 150,
not: ""
},
{
name: "orange",
energy: 118,
not: "peach"
},
{
name: "pineapple",
energy: 98,
not: ""
},
{
name: "coconut",
energy: 83,
not: ""
},
{
name: "peach",
energy: 65,
not: ""
},
{
name: "lemon",
energy: 36,
not: ""
}
]
const pick = (arr, n) => {
const r = [];
for (var i = 0; i < arr.length; i += n) {
var slice = [];
slice.push(arr[i]);
slice = slice.concat(arr.filter(function(x, ind) {
return x.name !== arr[i].name && x.not !== arr[i].name
}));
slice = slice.slice(0, n);
var name = slice.reduce((r, {
name
}) => r + name + "-", "");
name = name.replace(/\-$/, '');
const energy = slice.reduce((r, {
energy
}) => r + energy, 0);
r.push({
name,
energy
});
}
return r;
}
const result = pick(fruits, 2)
console.log(result)

Rapid way to find min and max values of a property in an array of objects

i have an array of objects like this:
arr = [
{name: "Alex", value: 1},
{name: "Bill", value: 2},
{name: "Jim", value: 3},
{name: "Dim", value: 5}
]
I want quick and clean way to have the min an max values of the value property
min = 1,
max = 5
You can use the reduce function on an array for min:
arr.reduce(function(prev, curr) {
return prev.value < curr.value ? prev : curr;
});
max would work in a similar way
Most performant would probably be a simple loop
arr = [
{name: "Alex", value: 1},
{name: "Bill", value: 2},
{name: "Jim", value: 3},
{name: "Dim", value: 5}
]
let min,max;
for (var i=arr.length; i--;) {
if ((!min) || arr[i].value < min) min = arr[i].value;
if ((!max) || arr[i].value > max) max = arr[i].value;
}
console.log(min, max)
Shortest to write, something like
arr = [
{name: "Alex", value: 1},
{name: "Bill", value: 2},
{name: "Jim", value: 3},
{name: "Dim", value: 5}
]
let m=Math,a=arr.map(z=>z.value);let [min,max]=[m.min(...a),m.max(...a)];
console.log(min,max)
var min = Number.POSITIVE_INFINITY,
max = Number.NEGATIVE_INFINITY;
arr.forEach(function(obj) {
min = Math.min(min, obj.value);
max = Math.max(max, obj.value);
});
You can use map() to return array of values and then use Math.max/min with spread syntax.
var arr = [{name:'Alex', value:1}, {name:'Bill', value:2},{name:'Jim', value: 3},{name: 'Dim', value:5}]
var values = arr.map(e => e.value);
var min = Math.min(...values);
var max = Math.max(...values);
console.log(max)
console.log(min)
You could either map the values and use Math function to get highest and the lowest value.
var arr = [{name:'Alex', value:1}, {name:'Bill', value:2},{name:'Jim', value: 3},{name: 'Dim', value:5}],
hash = arr.map(v => v.value),
min = Math.min.apply(Math, hash),
max = Math.max.apply(Math, hash);
console.log(min, max);
Or just sort the array of object based on the value property and choose the first and the last one.
var arr = [{name:'Alex', value:1}, {name:'Bill', value:2},{name:'Jim', value: 3},{name: 'Dim', value:5}],
hash = arr.sort((a,b) => a.value - b.value);
min = hash[0].value;
max = hash[hash.length-1].value;
console.log(min, max);
You can create a function to do it for you, and every time you need to find the min/max, it only takes you one line:
function findMM (arr) {
var minV;
var maxV;
var firstLoop = true;
arr.forEach(function(object){
if (firstLoop) {
minV = object.value;
maxV = object.value;
firstLoop = false;
} else {
if (object.value < minV){ minV = object.value }
if (object.value > maxV){ maxV = object.value }
}
});
return {min: minV, max: maxV};
}
//using the function
var results = findMM(arr);
console.log(JSON.stringify(results)); //output: {"min":1,"max":5}
Using reduce():
var arr = [{name:'Alex', value:1}, {name:'Bill', value:2},{name:'Jim', value: 3},{name: 'Dim', value:5}]
var result = arr.reduce(function(acc, val){
return { min: Math.min(acc.min, val.value),
max: Math.max(acc.max, val.value)}
}, {min: arr[0].value, max: arr[0].value});
console.log(result.max);
console.log(result.min);
You could sort your array using native Array.prototype.sort() and take the first and last value.
let data = [{
name: 'Ales',
value: 1
},
{
name: 'Dim',
value: 5
},
{
name: 'Bill',
value: 2
},
{
name: 'Jim',
value: 3
}
];
data = data.sort((a, b) => a.value - b.value);
let min = data [0].value;
let max = data [data .length - 1].value;
console.log('min:', min);
console.log('max:', max)
Notes:
If you use instead:
let min = data [0];
let max = data [data .length - 1];
you could return the full object which has a minimum or maximum value, which could be handy.

change the value of objects of the array

Here's is my array
Array1 = [{year: "2013", fruit: "banana", quantity: 1},{year: "2014", fruit: "orange", quantity: 1},{year: "2014", fruit: "banana", quantity: 2}]
And my function to duplicate Array1:
var Array2 = Array1;
for (var i = 0, len = Array1.length; i < len; i++) {
Array2[i] = Array1[i];
}
But I'd like to change in Array2 all the values my key "year" and put the value "AllYear":
Array2 = [{year: "AllYear", fruit: "banana", quantity: 1},{year: "AllYear", fruit: "orange", quantity: 1},{year: "2014", fruit: "banana", quantity: 2}]
Use map, but make sure you return a new object:
var Array2 = Array1.map(function (el) {
return { fruit: el.fruit, year: 'AllYear', quantity: el.quantity }
});
DEMO
//js
var Array2 = Array1
for (var i = 0, len = Array1.length; i < len; i++) {
Array2[i].year = "AllYear";
}
refer this solution : Jsfiddle
I hope this will help !
you can do like this
Array2 = Array1.slice(0); //copy array1 elements to array2
Array2 = Array2.map(function (el) {
var copy = {};
for (var attr in el) {
if (el.hasOwnProperty(attr)) copy[attr] = el[attr];
}
copy.year = 'AllYear';
return copy ;
});
var Array2 = Array1;
$.each(Array2,function(index,value) {
value.year = "AllYear";
});//returns what you excepted

How do you find Min & Max of a property in an array of objects in Javascript

I have the following javascript object:
Person1.Name = "John";
Person1.Age = 12;
Person2.Name = "Joe";
Person2.Age = 5;
I then have an array of persons, how do I find the Min/Max based on a persons age?
Any solution in Javascript or Jquery is acceptable.
your help is much appreciated.
Say your array looks like this:
var persons = [{Name:"John",Age:12},{Name:"Joe",Age:5}];
then you can:
var min = Math.min.apply(null, persons.map(function(a){return a.Age;}))
,max = Math.max.apply(null, persons.map(function(a){return a.Age;}))
[Edit] Added ES2015 method:
const minmax = (someArrayOfObjects, someKey) => {
const values = someArrayOfObjects.map( value => value[someKey] );
return {
min: Math.min.apply(null, values),
max: Math.max.apply(null, values)
};
};
console.log(
minmax(
[ {Name: "John", Age: 12},
{Name: "Joe", Age: 5},
{Name: "Mary", Age: 3},
{Name: "James sr", Age: 93},
{Name: "Anne", Age: 33} ],
'Age')
);
First you sort the array with a custom sorting function:
var sorted = persons.sort(function(a, b) {
if(a.Age > b.Age) return 1;
else if(a.Age < b.Age) return -1;
else return 0;
});
Then you can just take the first and last:
var min = sorted[0],
max = sorted[sorted.length - 1];

Categories

Resources