Making an exception when joining array's keys - javascript

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)

Related

To create ne array of objects with same key

I need to get an array by combining objects with the same type - adding their weight ․․․
const arr = [ {type: "a", weight: 10}, {type: "b", weight: 15}, {type: "a", weight: 20},]
Expected result;
[ {type: "a", weight: 30}, {type: "b", weight: 15},]
Here you go! Please comment if you need explanation as the code just uses for loop
const arr = [ {type: "a", weight: 10}, {type: "b", weight: 15}, {type: "a", weight: 20},]
for(let i = 0; i < arr.length; i++) {
for(let j = i + 1; j < arr.length; j++) {
if(arr[i].type == arr[j].type) {
arr[i].weight = arr[i].weight + arr[j].weight;
arr.splice(j, 1)
}
}
}
console.log(arr)

How to group items so as not to exceed a total amount in JavaScript?

I have an array of n objects in it. Each object has names as id, quantity, price and total. All of these have significance in solving this problem.
How can I create new arrays where sum of all total of their objects doesn't exceed 150.
My array:
let array = [{id: 1, quantity: 5, price: 10, total: 50}, {id: 2, quantity: 3, price: 100, total: 300}]
Expected result:
array1 = [{id: 1, quantity: 5, price: 10, total: 50}, {id: 2, quantity: 1, price: 100, total: 100}]
array2 = [{id: 2, quantity: 1, price: 100, total: 100}]
array3 = [{id: 2, quantity: 1, price: 100, total: 100}]
Conditions:
As mentioned, sum of totals in new arrays mustn't exceed 150
value of total must always be product of quantity and price in that object
object must keep dividing itself into new objects with smaller quantities until above conditions are met
quantity must be an integer
i tried this.
const itemsFinals = [];
const maxTotal = 150;
let totalGroup = 0;
for (i = 0; i < itemComprobantes.length; i++) {
if((itemComprobantes[i].total + totalGroup) < maxTotal){
itemsFinals.push(itemComprobantes[i]);
totalGroup += itemComprobantes[i].total;
}
}
let itemComprobantes = [
{id: 1, quantity: 5, price: 10, total: 50},
{id: 2, quantity: 1, price: 100, total: 100},
{id: 3, quantity: 1, price: 100, total: 100},
{id: 4, quantity: 1, price: 100, total: 30},
{id: 5, quantity: 1, price: 100, total: 80}
]
const itemsFinals = {}
const maxTotal = 150
let totalGroup = 0
let group = 1
for (i = 0; i < itemComprobantes.length; i++) {
if((itemComprobantes[i].total + totalGroup) > maxTotal){
group += 1
totalGroup = 0
}
if (itemsFinals['group '+group] === undefined) {
itemsFinals['group '+group] = []
}
itemsFinals['group '+group].push(itemComprobantes[i])
totalGroup += itemComprobantes[i].total
}
console.log(itemsFinals)
Here is my answer base on my comments.
Here is one way to do it. I know its long but give it a try
let array = [{id: 1, quantity: 5, price: 10, total: 50}, {id: 2, quantity: 3, price: 100, total: 300}, {id: 3, quantity: 5, price: 40, total: 200}, {id: 4, quantity: 2, price: 10, total: 20}];
const maxTotal = 150;
let new_arrays = {};
let index = 0;
let final_total = 0;
new_arrays['array_'+index] = [];
for (var obj of array) {
final_total += obj.total;
while (final_total > maxTotal) {
let exceed_value = final_total - maxTotal; // 350 - 150 = 200
let retain_quantity = parseInt((obj.total - exceed_value) / obj.price); // (300 - 200)/100 = 2
let remaining_quantity = obj.quantity - retain_quantity;
if (retain_quantity != 0) {
retain_obj = Object.assign({}, obj);
retain_obj.quantity = retain_quantity;
retain_obj.total = retain_quantity * obj.price;
new_arrays["array_"+index].push(retain_obj);
}
index++;
new_arrays['array_'+index] = [];
new_obj = Object.assign({}, obj, {quantity: remaining_quantity, total: remaining_quantity * obj.price})
new_arrays["array_"+index].push(new_obj);
// console.log(new_obj);
obj = new_obj;
final_total = remaining_quantity * obj.price;
new_arrays['array_'+index].pop(); // if loop is to repeat again
}
new_arrays["array_"+index].push(obj); // prints new and remaining quantities
}
console.log(new_arrays)

Merge arrays into one

I'm trying merge arrays into one in javascript.
I have this Array:
[{ID: 111, SEG: 4}, {ID: 111, SEG:
3}]
And I need this:
[{ID: 111, SEG: [3, 4]}]
This can be approximated to a solution, depending on the data:
var items = [
{
id: 1,
value: 5
},
{
id: 1,
value: 3
},
{
id: 2,
value: 40
},
{
id: 2,
value: 35
}
];
var group = function (arr, groupBy) {
var values = {};
arr.forEach(function (element) {
var item = element;
var index = item[groupBy];
if (!values[index]) {
values[index] = item;
}
else {
item.value += values[index].value;
}
values[index] = item;
});
return Object.keys(values).map(function (k) { return values[k]; });
};
console.log(group(items, 'id'));
The Problem can be solved using reduce.
let dataJ = [{ID: 111, SEG: 4}, {ID: 111, SEG: 3}]
let newData = dataJ.reduce(function(acc, curr) {
let index = acc.findIndex(item => item.ID === curr.ID);
if (index === -1) {
acc.push(curr);
} else {
if (!acc[index].SEG || !Array.isArray(acc[index].SEG)) {
acc[index].SEG = [];
}
acc[index].SEG.push(curr.SEG);
}
return acc;
}, []);
console.log(newData); // [{ID: 111, SEG: [3, 4]}]

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

how to iterate throught an array of objects and concate the contents

I have the object (obj1) that is posted below. As shown in it, it contains an array of objects called "favoritePlayers".
what I am trying to do is, to create a function or add an array prototype so that I can iterate through each element in the array separately and get the following output:
"messi plays in barcelona"
"totti plays in roma"
I tried to solve it as shown below but what I get is
[ 'undefinedplays in[object Object]',
'undefinedplays in[object Object]' ]
obj1:
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [
{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
],
calcAvgScore: function () {
var sumOfScores = this.score.reduce(function (prev, cur, index, array)
{
return prev + cur;
})
return (sumOfScores / this.score.length);
},
myFavoritePlayersInfo: function () {
console.log(this.favoritePlayers.join());
},
}
my attempts:
//this code was added outside the scope of obj1
Array.prototype.concat1 = ( (array) => {
var tempArray = [];
for (var i = 0; i < array.length; i++) {
tempArray[i] = array.slice(i, i+1).name + "plays in" + array.slice(i,
i+1);
}
return tempArray;
});
update_1
I added the following lines to obj1:
getPlaysIn:function() {
this.favoritePlayers.forEach( (favoritePlayer)=> {
return favoritePlayer.name + " plays in " + favoritePlayer.club;
and I call it as follows:
console.log(obj1.getPlaysIn());
but the results i get is
undefined
You can use Array#map to iterate the players, and create the array you want:
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
],
getPlaysIn() {
return this.favoritePlayers.map(function(player) {
return player.name + ' plays in ' + player.club;
});
}
};
console.log(obj1.getPlaysIn());
Just iterate the favoritePlayers array
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
]
}
obj1.favoritePlayers.forEach(function(item) {
console.log(item.name + ' plays ' + item.club)
})
If you want to use prototype
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
]
}
Array.prototype.customForEach = function() {
for (let i = 0; i < this.length; i++) {
console.log(this[i].name + ' plays ' + this[i].club);
}
}
obj1.favoritePlayers.customForEach();
Iterate through the object and return it the way you see fit.
let playerInfo = obj1.favoritePlayers.map(playerObj => {
return playerObj["name"] + "plays for " + playerObj["club"];
});
Try below code.
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [
{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
],
getPlaysIn:function() {
var returnVal = "";
this.favoritePlayers.forEach( (favoritePlayer)=> {
returnVal += favoritePlayer.name + " plays in " + favoritePlayer.club+"\n";
});
return returnVal;
}
}
console.log(obj1.getPlaysIn());
var obj1 = {
score: [10, 22, 30, 55, 70, 90],
lettersOfMyName: ["a", "m", "r"],
avgScore: null,
favoritePlayers: [{
name: "messi",
club: "barcelona"
},
{
name: "totti",
club: "roma"
}
]
}
var a = obj1.favoritePlayers;
for(var i = 0; i<a.length; i++){
console.log(a[i].name+ " " + "plays " +" "+ a[i].club)
};

Categories

Resources