I need help, I’m new to js and have to do this task. I’m confused what I’m doing wrong…
var products = [
product = {
id: 1,
name: "green",
},
product = {
id: 2,
name: "red",
},
product = {
id: 3,
name: "black",
},
];
var myWishlist = [
wishlist = {
id: 1,
productId: 4,
},
wishlist = {
id: 2,
productId: 2,
},
wishlist = {
id: 3,
productId: 2,
},
];
for (var i = 0; i < myWishlist.length; ++i) {
var currentWishlistProductId = myWishlist[i].productId;
for (var j = 0; j < products.length; ++j) {
var currentProductId = products[i].id;
if (currentWishlistProductId == currentProductId) {
console.log(
"Whishlist id: " +
myWishlist[i].id +
"Product name: " +
products[i].name,
);
}
}
}
Now output is: Whishlist id: 2 Product name: red
Output should look like this:
Whishlist id: 2 Product name: red
Whishlist id: 3 Product name: red
First of all, you need a data structure which is free of syntactic errors. You may have a look to Object initializer and put the objects inside of an Array without assigning to a variable (which makes no sense).
The a good idea is to use a data structure which gives the opportunity to have a fast access to data with a key, like an Object or Map. The later one accepts any type of variable as key and as value.
At last, you need only a single loop and get the wanted property from the mapped object.
var products = [{ id: 1, name: "green" }, { id: 2, name: "red" }, { id: 3, name: "black" }],
myWishlist = [{ id: 1, productId: 4 }, { id: 2, productId: 2 }, { id: 3, productId: 2 }],
productsMap = new Map(products.map(o => [o.id, o]));
for (var i = 0; i < myWishlist.length; ++i) {
console.log("Whishlist id:", myWishlist[i].id, "Product name:", (productsMap.get(myWishlist[i].productId) || {}).name);
}
Try this code below:
var products = [{ id: 1, name: "green" }, { id: 2, name: "red" }, { id: 3, name: "black" }],
myWishlist = [{ id: 1, productId: 4 }, { id: 2, productId: 2 }, { id: 3, productId: 2 }],
res = products.map(function (item) {
myWishlist.map(function (wishItem) {
if(item.id == wishItem.productId){
console.log("Whishlist id: "+wishItem.id+" Product name: "+item.name)
}
});
});
console.log(res)
Use "j" iterator for products array
var products = [
product = {
id: 1,
name: "green",
},
product = {
id: 2,
name: "red",
},
product = {
id: 3,
name: "black",
},
];
var myWishlist = [
wishlist = {
id: 1,
productId: 4,
},
wishlist = {
id: 2,
productId: 2,
},
wishlist = {
id: 3,
productId: 2,
},
];
for (var i = 0; i < myWishlist.length; ++i) {
var currentWishlistProductId = myWishlist[i].productId;
for (var j = 0; j < products.length; ++j) {
var currentProductId = products[j].id; // change i-> j
if (currentWishlistProductId == currentProductId) {
console.log(
"Whishlist id: " +
myWishlist[i].id +
"Product name: " +
products[j].name, // Change i->j
);
}
}
}
Related
So I have an array with 45 items, each item has 2 items, local and visitor team.
I need to create a function that creates 9 matchdays with 5 games in each matchday, but the games can't repeat.
I tried doing this:
const getRandomGame = (items, idsToAvoid) => {
const game = getRandomFromArray(items);
if (idsToAvoid.includes(game[0].id, game[1].id))
return getRandomGame(items, idsToAvoid);
return game;
};
const getRandomFromArray = (items) => {
return items[Math.floor(Math.random() * items.length)];
};
// this is inside another function that tries to generate the matchdays
for (let i = 0; i < 9; i++) {
counter++;
let games = [];
let avoidIds = [];
for (let j = 0; j < 5; j++) {
const game = getRandomGame(copyFinalGames, avoidIds);
const localRng = Math.random() < 0.5;
const local = localRng ? game[0] : game[1];
const visitor = localRng ? game[1] : game[0];
avoidIds.push(local.id, visitor.id);
games.push({
id: counter,
local,
visitor,
});
copyFinalGames = copyFinalGames.filter(
(item) => !(item[0].id === game[0].id && item[1].id === game[1].id)
);
}
gamedays.push({
id: i + 1,
games,
});
}
Which doesn't quite work (games are being repeated) + it's not efficient cause it tries to brute force the rule out repeated games. Any ideas?
The original array looks like this:
[{ id: 1 }, { id: 2}],
[{ id: 3 }, { id: 4}],
[{ id: 5 }, { id: 6}] // here only showing three rows, but it has the 45 possible games
OK, here's an attempt:
const matchupList =
[
[{ id: 1 }, { id: 2}],
[{ id: 3 }, { id: 4}],
[{ id: 5 }, { id: 6}],
[{ id: 6 }, { id: 5}],
[{ id: 3 }, { id: 9}],
[{ id: 8 }, { id: 2}],
[{ id: 4 }, { id: 1}],
[{ id: 2 }, { id: 6}],
[{ id: 7 }, { id: 8}],
[{ id: 5 }, { id: 3}],
[{ id: 3 }, { id: 1}],
[{ id: 2 }, { id: 7}],
[{ id: 7 }, { id: 1}],
[{ id: 4 }, { id: 6}],
[{ id: 7 }, { id: 2}],
[{ id: 8 }, { id: 1}],
[{ id: 9 }, { id: 3}],
[{ id: 5 }, { id: 4}],
[{ id: 5 }, { id: 0}],
[{ id: 0 }, { id: 3}],
[{ id: 1 }, { id: 0}],
[{ id: 0 }, { id: 8}],
[{ id: 9 }, { id: 8}]
];
const pickMatch = (list) => list[Math.floor(Math.random() * list.length)];
const pickMatchDay = (matchupList, matchDaySize) =>
{
let matchChosen;
let teamSeen;
let workingList;
do
{
matchChosen = [];
teamSeen = [];
// Create a copy of the original matchup list so we can remove matches we've already tried
workingList = matchupList.concat();
while(matchChosen.length < matchDaySize && workingList.length)
{
let local, visitor;
let teamPairing = pickMatch(workingList);
let fromId = matchupList.indexOf(teamPairing);
teamPairing = teamPairing.map(i => i.id);
// If this pairing has NO teams we've already seen...
if(teamPairing.findIndex(i => teamSeen.includes(i)) === -1)
{
// Randomly decide who is local/visitor
if(Math.random() < 0.5)
[local, visitor] = teamPairing;
else
[visitor, local] = teamPairing;
matchChosen.push(
{
id: matchChosen.length + 1,
local,
visitor,
fromId
});
// Push this pairing's teams to the list of teams we've seen
teamSeen.push(...teamPairing);
}
// Remove this matchup from the possible matchups we can choose
workingList.splice(workingList.indexOf(teamPairing), 1);
}
// Due to the limited number of pairings available (and that pairings are variable),
// it's quite possible we'll reach this point with only 3 or 4 matches chosen,
// but having exhausted all available matchups.
// If this happens, we start over.
// Not really necessary if you can guarantee 45 matchups and 5 matches per day
} while(matchChosen.length < matchDaySize);
return(matchChosen);
};
const gamedays = [];
for(let index = 0; index < 5; index++)
gamedays.push({id: index + 1, games: pickMatchDay(matchupList, 5)});
console.log(gamedays);
Some notes:
Pairings can still be repeated across different days. You might find that team 1 plays team 2 on both day 1 and day 3, for instance.
pickMatchDay has a real possibility of infinitely looping, e.g. you can ask for 6 games, which is just impossible with only 10 teams.
I have two lists and would like to update one with the other on a matching index.
let cart = [{
header: some_data,
items: [{
id: 7,
properties: some_props_7,
time: 12345
}, {
id: 19,
properties: some_props_19,
time: 13344
}, {
id: 24,
properties: some_props_24,
time: 14342
}]
}, etc.];
let newData = [{
header: some_data,
items: [{
id: 19,
properties: some_new_props_19,
time: 17744
}, {
id: 24,
properties: some_new_props_24,
time: 18342
}]
}, etc.];
I am iterating over the cart, but am not coming up with an efficient way to update. I think I need another for loop in the "update cart" section, but that seems sub-optimal to me.
k is a list of indices
let i = 0, j = 0, l = cart.length;
for (i = 0; i < l; i++) {
let m = cart[i]['items'].length;
for (j = 0; j < m; j++) {
// update cart index with associated newData matching on id
}
}
How do I update the header and items data in the cart from a dynamic newData list?
Filter out overlaps and concatenate with new items:
let cart = {
header: 'some_data',
items: [{
id: 7,
properties: 'some_props_7',
time: 12345
}, {
id: 19,
properties: 'some_props_19',
time: 13344
}, {
id: 24,
properties: 'some_props_24',
time: 14342
}]
};
let newData = {
header: 'some_data',
items: [{
id: 19,
properties: 'some_new_props_19',
time: 17744
}, {
id: 24,
properties: 'some_new_props_24',
time: 18342
}]
};
//TEST
console.log(
cart.items.filter(item => !newData.items.map(i => i.id).includes(item.id)).concat(newData.items)
);
Updated in response to comments
It now maps properly over lists.
var cart = [{
header: 'some_data',
items: [{
id: 7,
properties: 'some_props_7',
time: 12345
}, {
id: 19,
properties: 'some_props_19',
time: 13344
}, {
id: 24,
properties: 'some_props_24',
time: 14342
}]
}];
var newData = [{
header: 'some_data',
items: [{
id: 19,
properties: 'some_new_props_19',
time: 17744
}, {
id: 24,
properties: 'some_new_props_24',
time: 18342
}]
}];
//TEST
cart = cart
//Modify existing data elements
.map(function(car) {
newData.forEach(function(data) {
if (data.header === car.header) {
car.items = car.items.filter(function(item) {
return !data.items.map(function(i) {
return i.id;
}).includes(item.id);
}).concat(data.items);
}
});
return car;
})
//Add new data elements
.concat(newData.filter(function(data) {
return !cart.some(function(car) {
return car.header === data.header;
});
}));
console.log(cart);
This question already has answers here:
How to get the difference between two arrays of objects in JavaScript
(22 answers)
Closed 1 year ago.
I need some help. How can I get the array of the difference on this scenario:
var b1 = [
{ id: 0, name: 'john' },
{ id: 1, name: 'mary' },
{ id: 2, name: 'pablo' },
{ id: 3, name: 'escobar' }
];
var b2 = [
{ id: 0, name: 'john' },
{ id: 1, name: 'mary' }
];
I want the array of difference:
// [{ id: 2, name: 'pablo' }, { id: 3, name: 'escobar' }]
How is the most optimized approach?
I´m trying to filter a reduced array.. something on this line:
var Bfiltered = b1.filter(function (x) {
return x.name !== b2.reduce(function (acc, document, index) {
return (document.name === x.name) ? document.name : false
},0)
});
console.log("Bfiltered", Bfiltered);
// returns { id: 0, name: 'john' }, { id: 2, name: 'pablo' }, { id: 3, name: 'escobar' } ]
Thanks,
Robot
.Filter() and .some() functions will do the trick
var b1 = [
{ id: 0, name: 'john' },
{ id: 1, name: 'mary' },
{ id: 2, name: 'pablo' },
{ id: 3, name: 'escobar' }
];
var b2 = [
{ id: 0, name: 'john' },
{ id: 1, name: 'mary' }
];
var res = b1.filter(item1 =>
!b2.some(item2 => (item2.id === item1.id && item2.name === item1.name)))
console.log(res);
You can use filter to filter/loop thru the array and some to check if id exist on array 2
var b1 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }, { id: 2, name: 'pablo' }, { id: 3, name: 'escobar' } ];
var b2 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }];
var result = b1.filter(o => !b2.some(v => v.id === o.id));
console.log(result);
Above example will work if array 1 is longer. If you dont know which one is longer you can use sort to arrange the array and use reduce and filter.
var b1 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }, { id: 2, name: 'pablo' }, { id: 3, name: 'escobar' } ];
var b2 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }];
var result = [b1, b2].sort((a,b)=> b.length - a.length)
.reduce((a,b)=>a.filter(o => !b.some(v => v.id === o.id)));
console.log(result);
Another possibility is to use a Map, allowing you to bring down the time complexity to O(max(n,m)) if dealing with a Map-result is fine for you:
function findArrayDifferences(arr1, arr2) {
const map = new Map();
const maxLength = Math.max(arr1.length, arr2.length);
for (let i = 0; i < maxLength; i++) {
if (i < arr1.length) {
const entry = arr1[i];
if (map.has(entry.id)) {
map.delete(entry.id);
} else {
map.set(entry.id, entry);
}
}
if (i < arr2.length) {
const entry = arr2[i];
if (map.has(entry.id)) {
map.delete(entry.id);
} else {
map.set(entry.id, entry);
}
}
}
return map;
}
const arr1 = [{id:0,name:'john'},{id:1,name:'mary'},{id:2,name:'pablo'},{id:3,name:'escobar'}];
const arr2 = [{id:0,name:'john'},{id:1,name:'mary'},{id:99,name:'someone else'}];
const resultAsArray = [...findArrayDifferences(arr1,arr2).values()];
console.log(resultAsArray);
I have been trying to delete an element with an ID in nested array.
I am not sure how to use filter() with nested arrays.
I want to delete the {id: 111,name: "A"} object only.
Here is my code:
var array = [{
id: 1,
list: [{
id: 123,
name: "Dartanan"
}, {
id: 456,
name: "Athos"
}, {
id: 789,
name: "Porthos"
}]
}, {
id: 2,
list: [{
id: 111,
name: "A"
}, {
id: 222,
name: "B"
}]
}]
var temp = array
for (let i = 0; i < array.length; i++) {
for (let j = 0; j < array[i].list.length; j++) {
temp = temp.filter(function(item) {
return item.list[j].id !== 123
})
}
}
array = temp
You can use the function forEach and execute the function filter for every array list.
var array = [{ id: 1, list: [{ id: 123, name: "Dartanan" }, { id: 456, name: "Athos" }, { id: 789, name: "Porthos" }] }, { id: 2, list: [{ id: 111, name: "A" }, { id: 222, name: "B" }] }];
array.forEach(o => (o.list = o.list.filter(l => l.id != 111)));
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
To remain the data immutable, use the function map:
var array = [{ id: 1, list: [{ id: 123, name: "Dartanan" }, { id: 456, name: "Athos" }, { id: 789, name: "Porthos" }] }, { id: 2, list: [{ id: 111, name: "A" }, { id: 222, name: "B" }] }],
result = array.map(o => ({...o, list: o.list.filter(l => l.id != 111)}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could create a new array which contains elements with filtered list property.
const result = array.map(element => (
{
...element,
list: element.list.filter(l => l.id !== 111)
}
));
You can use Object.assign if the runtime you are running this code on does not support spread operator.
Array.filter acts on elements:
var myArray = [{something: 1, list: [1,2,3]}, {something: 2, list: [3,4,5]}]
var filtered = myArray.filter(function(element) {
return element.something === 1;
// true = keep element, false = discard it
})
console.log(filtered); // logs [{something: 1, list: [1,2,3]}]
You can use it like this:
var array = [{
id: 1,
list: [{
id: 123,
name: "Dartanan"
}, {
id: 456,
name: "Athos"
}, {
id: 789,
name: "Porthos"
}]
}, {
id: 2,
list: [{
id: 111,
name: "A"
}, {
id: 222,
name: "B"
}]
}]
for (var i = 0; i < array.length; ++i) {
var element = array[i]
// Filter the list
element.list = element.list.filter(function(listItem) {
return listItem.id !== 111 && listItem.name !== 'A';
})
}
console.log(array)
I have an array of objects:
[{
id: 1,
name: 'kitten'
}, {
id: 2,
name: 'kitten'
},{
id: 3,
name: 'cat
}]
How do I remove the second kitten? Sorting into an array of names doesn't work, because I can't know if I am deleting id 1 or or id 2. So, I'm not quite sure how to do this.
You can use an additional hash-map to store names found so far. When you process a next object if it's name is already in the hash-map it is a duplicate and you can remove it.
var duplicates = {};
for (var i = 0; i < array.length) {
var obj = array[i];
if (! duplicates[obj.name]) {
duplicates[obj.name] = 1;
i++;
} else {
array.splice(i, 1);
}
}
there is the lodash library.
You could use the uniq
var array = [{
id: 1,
name: 'kitten'
}, {
id: 2,
name: 'kitten'
},{
id: 3,
name: 'cat'
}];
var asd = _.uniq(array,'name');
console.log(asd);
Gives an output:
[ { id: 1, name: 'kitten' }, { id: 3, name: 'cat' } ]
as it written in the documentation "only the first occurence of each element is kept".
var arr =[{
id: 1,
name: 'kitten'
}, {
id: 2,
name: 'kitten'
},{
id: 3,
name: 'cat'
}];
var results = [];
var idsSeen = {}, idSeenValue = {};
for (var i = 0, len = arr.length, name; i < len; ++i) {
name = arr[i].name;
if (idsSeen[name] !== idSeenValue) {
results.push(arr[i]);
idsSeen[name] = idSeenValue;
}
}
console.log(results);