I need: for each property id in first array that equals id property in second array change property liked in first array from false to true. So very specifically, looking at second array we can conclude that in first array objects with id value 34, 31 and 35 will now have liked:true. How to accomplish such code?
First array:
Array [
Object {
"Aw8AUj1mPkON1Fd1s6LhkNETHfb2": "liked",
"avatar": null,
"hugCount": 2,
"id": 35,
"liked": false,
"name": "fhfdhdhf",
"text": "Yoho",
"timestamp": 1610471860157,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
},
Object {
"avatar": null,
"hugCount": 1,
"id": 34,
"liked": false,
"mood": 2,
"name": "fhfdhdhf",
"text": "I'm fine today.",
"timestamp": 1607943705709,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
},
Object {
"avatar": "https://firebasestorage.googleapis.com/v0/b/eleph-6fee9.appspot.com/o/avatars%2Fm2OnHQiDuVM3Bp40Sc2ikqqmiQz2?alt=media&token=a2d66c27-ec63-422d-a3e4-76fcf7a12134",
"hugCount": 3,
"id": 33,
"liked": false,
"mood": 3,
"name": "Matko",
"text": "evotv",
"timestamp": 1606350804169,
"uid": "m2OnHQiDuVM3Bp40Sc2ikqqmiQz2",
}]
and this first array goes on for long but I closed it here cause its enough to show it
Second Array:
Array [
Object {
"id": 34,
"userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2",
},
Object {
"id": 31,
"userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2",
},
Object {
"id": 35,
"userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2",
},
]
You can use Array.prototype.some() to test if any objects in the second array have matching ids and assign the returned boolean to liked.
const
arr1 = [{ "Aw8AUj1mPkON1Fd1s6LhkNETHfb2": "liked", "avatar": null, "hugCount": 2, "id": 35, "liked": false, "name": "fhfdhdhf", "text": "Yoho", "timestamp": 1610471860157, "uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1", }, { "avatar": null, "hugCount": 1, "id": 34, "liked": false, "mood": 2, "name": "fhfdhdhf", "text": "I'm fine today.", "timestamp": 1607943705709, "uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1", }, { "avatar": "https://firebasestorage.googleapis.com/v0/b/eleph-6fee9.appspot.com/o/avatars%2Fm2OnHQiDuVM3Bp40Sc2ikqqmiQz2?alt=media&token=a2d66c27-ec63-422d-a3e4-76fcf7a12134", "hugCount": 3, "id": 33, "liked": false, "mood": 3, "name": "Matko", "text": "evotv", "timestamp": 1606350804169, "uid": "m2OnHQiDuVM3Bp40Sc2ikqqmiQz2", }],
arr2 = [{ "id": 34, "userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2", }, { "id": 31, "userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2", }, { "id": 35, "userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2", },]
arr1.forEach(o => o.liked = arr2.some(({ id }) => o.id === id));
console.log(arr1)
This should get you the answer in O(n).
First array = va
Second array = ta
function test(arr1, arr2){
let em = {};
arr2.forEach(({id}) => em[id] = 1);
return arr1.map(el => {
em[el.id] ? el.liked = true : null;
return el;
})
}
va = test(va, ta);
const arr1 = [{id: 1, liked: false}, {id: 2, liked: false}, {id: 3, liked: false}];
const arr2 = [{id: 1}, {id: 3}];
arr1.forEach(element1 => {
element1.liked = arr2.some((element2) => {
return element1.id === element2.id;
});
});
Explanation:
Iterate through each array element in "arr1" (array of objects), then assign the "element1.liked" with the value returns from 'some' method. that method actually iterate through each element in "arr2" and assign it to element2 (similar to forEach) and return boolean value if the id's are equal, same boolean value that assigns to element1.liked. Hope that understandable and accurate enough.
Related
I have an array of object and I want to copy that array of object to another array while modifying some items, like copying id only by ascending order and copying only the value of trophies of basketball to trophies. How to do it?
const item = [{
"id": 33,
"name": "John"
"trophies": {
"basketball" : 2,
"baseball" : 5
},
"profile": "profile/212"
}
{
"id": 12,
"name": "Michael"
"trophies": {
"basketball" : 6,
"baseball" : 7
},
"profile": "profile/341"
}
]
I want the above array of object after copying to look something like
const item2 = [{
"id": 12,
"name": "Michael"
"trophies": 6,
"profile": "http://collegeprofile.com/profile/341"
},
{
"id": 33,
"name": "John"
"trophies": 2,
"profile": "http://collegeprofile.com/profile/212"
}
]
You can sort by id ascending order using Array.prototype.sort
And map basketball value to trophies using Array.prototype.map.
const item = [{
"id": 33,
"name": "John",
"trophies": {
"basketball": 2,
"baseball": 5
},
"profile": "profile/212"
}, {
"id": 12,
"name": "Michael",
"trophies": {
"basketball": 6,
"baseball": 7
},
"profile": "profile/341"
}];
const output = item.sort((a, b) => (a.id - b.id)).map((item) => ({
...item,
trophies: item.trophies.basketball,
profile: "http://collegeprofile.com/" + item.profile
}));
console.log(output);
I came up with an example from another topic which can filter nested array from another array where filter values stored.
Interestingly when there is single element in array,it doesnt work well.
const data = [
{
"guid": "j5Dc9Z",
"courses": [
{
"id": 3,
"name": "foo"
}
]
},
{
"guid": "a5gdfS",
"courses": [
{
"id": 1,
"name": "bar"
},
{
"id": 3,
"name": "foo"
}
]
},
{
"guid": "jHab6i",
"courses": [
{
"id": 7,
"name": "foobar"
}
]
}
];
const courses = [3];
const r = data.filter(d => d.courses.every(c => courses.includes(c.id)));
console.log(r);
in case of my example,we are supposed to see two 3 but instead it gives us first one.How can I filter this nested array with multiple values or single?
You are asking for ALL/EVERY object to have id == 3 here, but what you want is to have ANY/SOME of the objects to have id == 3, like here:
const data = [{
"guid": "j5Dc9Z",
"courses": [{
"id": 3,
"name": "foo"
}]
},
{
"guid": "a5gdfS",
"courses": [{
"id": 1,
"name": "bar"
}, {
"id": 3,
"name": "foo"
}]
}, {
"guid": "jHab6i",
"courses": [{
"id": 7,
"name": "foobar"
}]
}
];
const courses = [3];
const r = data
.filter(d => d.courses.some(c => courses.includes(c.id)))
.map(d => ({ ...d, courses: d.courses.filter(c => courses.includes(c.id))
}));
console.log(r);
If you want to find all items in the data that contain all of the ids found in the const courses, then you need to invert your filtering.
const data = [
{"guid": "j5Dc9Z", "courses": [{"id": 3, "name": "foo"}]},
{"guid": "a5gdfS", "courses": [{"id": 1, "name": "bar"}, {"id": 3, "name": "foo"}]},
{"guid": "jHab6i", "courses": [{"id": 7, "name": "foobar"}]}
];
const courses = [3];
const r = data.filter(d => courses.every(courseId => d.courses.find(({
id
}) => courseId === id)));
console.log(r);
I have the array:
var tabs = [
{"id": 1, "Name": "Top", "Paris": 1, "London": 1, "Rome": 1},
{"id": 2, "Name": "Best", "Paris": 1, "London": 0, "Rome": 0},
{"id": 3, "Name": "Cheap", "Paris": 0, "London": 1, "Rome": 0}
];
How can I write a function that receives as argument one of the towns (London or Paris or Rome) different each time and returns the elements of the array which the argument is 1? For example, I want to take all the elements where London=1.
var tabs= [
{ "id": 1, "Name": "Top","Paris":1,"London":1, "Rome":1},
{ "id": 2, "Name": "Best","Paris":1,"London":0,"Rome":0},
{ "id": 3, "Name": "Cheap","Paris":0,"London":1,"Rome":0}
];
var getElementsWith=function(array,name){
var myElements=[];
array.forEach(function(tab){
if(tab[name]===1)
myElements.push(tab);
});
return myElements;
};
console.log(getElementsWith(tabs,"Paris"));
You can use Array.filter:
function filterList(cityName) {
return tabs.filter(function(o) {
return o[cityName] === 1;
});
}
You could use a generic function, which takes the array, key and value, you are looking for. Then use Array#filter for the sub set.
function filter(array, key, value) {
return array.filter(function (object) {
return object[key] === value;
});
}
var tabs = [{ "id": 1, "Name": "Top","Paris":1,"London":1, "Rome":1 },{ "id": 2, "Name": "Best","Paris":1,"London":0,"Rome":0 },{ "id": 3, "Name": "Cheap","Paris":0,"London":1,"Rome":0 }],
result = filter(tabs, 'London', 1);
console.log(result);
I have 2 arrays of objects: itemsList and itemsFetched. All of the objects inside each array have the same structure (nr of key/values). One of those keys has the same 'meaning' but a different name (item_id on itemsList, id on itemsFetched ). Their values are the same.
I need to filter the itemsList array and leave only the objects that have the item_id value equal to the id value on itemsFetched. Then copy(add) the key/value count from each object on the itemsFetched array (which matches the item_id=id) to the filtered array.
I've a working code but I'm sure it isnt the best way to solve this problem. I've already asked something similar before (regarding the 'filter' part) which solved my problem, but since I had to add the 'count' part after the filtering, I ended up refactoring the whole thing.
itemsList (sample)
[
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
},
{
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
},
{
"id": 401,
"name": "Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 901,
"name": "Incubator (Unlimited)",
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}
]
itemsFetched (sample)
[
{
"item_id": 1,
"count": 50,
"unseen": true
},
{
"item_id": 401,
"count": 2,
"unseen": true
},
{
"item_id": 901,
"count": 1,
"unseen": true
}
]
resultArray (what I want in the end)
[
{
"id": 1,
"name": "Pokeball",
"count": 50,
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png",
},
{
"id": 401,
"name": "Incense",
"count": 2,
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 901,
"name": "Incubator (Unlimited)",
"count": 1,
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}
]
my current code (working)
let arr = [];
itemsFetched.forEach((item) => {
itemsList.forEach((item2) => {
if (item.item_id === item2.id) {
arr.push({
"id": item.item_id,
"name": item2.name,
"count": item.count,
"img": item2.img
});
}
});
});
PS: I'm able to use ES6/7 syntax/features.
You can use hash map to reduce Time complexitly, your algorithm is O(m*n), The follow is O(m+n+r)
const itemsMap = itemsList.reduce((map, item) => {
map[item.id] = item
return map
}, {})
const results = itemsFetched
.filter((item) => itemsMap.hasOwnProperty(item.item_id))
.map((item) => ({
id: item.item_id,
name: itemsMap[item.item_id].name,
count: item.count,
img: itemsMap[item.item_id].img,
}))
Use a for ... of loop (an ES6 feature) in conjunction with Array#map.
This makes it much easier to return the merged object the first time you find a match, which is a logically optimization because neither list should contain more than one entry with a given id.
const result = itemsFetched.map(data => {
for (let item of itemsList) {
if (data.item_id === item.id) {
return {
id: item.id,
name: item.name,
count: data.count,
img: item.img
}
}
}
})
Snippet:
const itemsList = [{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
}, {
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
}, {
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
}, {
"id": 401,
"name": "Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
}, {
"id": 901,
"name": "Incubator (Unlimited)",
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}]
const itemsFetched = [{
"item_id": 1,
"count": 50,
"unseen": true
}, {
"item_id": 401,
"count": 2,
"unseen": true
}, {
"item_id": 901,
"count": 1,
"unseen": true
}]
const result = itemsFetched.map(data => {
for (let item of itemsList) {
if (data.item_id === item.id) {
return {
id: item.id,
name: item.name,
count: data.count,
img: item.img
}
}
}
})
console.log(result)
One way to improve is to use for..of statement instead of forEach for the inner loop. This helps break from the loop once the id matches. There is no direct way to break from forEach method.
let arr = [];
itemsFetched.forEach((item) => {
for (let item2 of itemsList) {
if (itemsFetched.item_id === itemsList.id) {
arr.push({
"id": itemsFetched.item_id,
"name": itemsList.name,
"count": itemsFetched.count,
"img": itemsList.img
});
break;
}
}
});
Like this?
var itemsList = [
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
},
{
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
},
{
"id": 401,
"name": "Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 901,
"name": "Incubator (Unlimited)",
"img": "http://www.serebii.net/pokemongo/items/eggincubator.png"
}
];
var itemsFetched = [
{
"item_id": 1,
"count": 50,
"unseen": true
},
{
"item_id": 401,
"count": 2,
"unseen": true
},
{
"item_id": 901,
"count": 1,
"unseen": true
}
]
let arr = [];
itemsFetched.forEach((item) => {
itemsList.forEach((item2) => {
if (item.item_id == item2.id) {
arr.push({
"id": item.item_id,
"name": item2.name,
"count": item.count,
"img": item2.img
});
}
});
});
console.log(arr);
I have an array of objects that looks like this
[{
"name": "Agile Process",
"id": 27,
"score": 3,
"source": "Self"
},{
"name": "Agile Process",
"id": 27,
"score": 4,
"source": "Trainer"
},{
"name": "2 & 3 Tier Architecture",
"id": 37,
"score": 4,
"source": "Self"
},{
"name": "2 & 3 Tier Architecture",
"id": 37,
"score": 5,
"source": "Trainer"
}]
I want to be able to produce something like this, I have been trying hard but I do not seems to get a hang of it.
[
{
"name": "Agile Process",
"id": 7,
"data": [
{
"score": 3,
"source": "Self"
},{
"score": 4,
"source": "Trainer"
}
]
},
{
"name": "2 & 3 Tier Architecture",
"id": 37,
"data": [
{
"score": 4,
"source": "Self"
},{
"score": 5,
"source": "Trainer"
}]
}
];
How do I go about solving this problem?
One possible approach:
_.values(_.reduce(arr, function(acc, el) {
var id = el.id;
if (!acc.hasOwnProperty(id)) {
acc[id] = _.pick(el, 'id', 'name');
acc[id].data = [];
}
acc[id].data.push(_.pick(el, 'score', 'source'));
return acc;
}, {}));
Demo. It's a common method when you need to group things up.
Here's a pure javascript solution: use reduce method on the initial array using as the accumulator the result array (empty at first) which will store the transformed data. And as reduce method loops through the items of the initial array, check if the result array contains an element with id of the current item. If so, then just add new data to it, else create a new item in the result array.
var data = [{
"name": "Agile Process",
"id": 27,
"score": 3,
"source": "Self"
},{
"name": "Agile Process",
"id": 27,
"score": 4,
"source": "Trainer"
},{
"name": "2 & 3 Tier Architecture",
"id": 37,
"score": 4,
"source": "Self"
},{
"name": "2 & 3 Tier Architecture",
"id": 37,
"score": 5,
"source": "Trainer"
}];
var newData = [];
newData = data.reduce(function(acc, current) {
var existingArr = acc.filter(function(x) { return x.id === current.id });
if(existingArr.length === 0) {
acc.push({ name: current.name, id: current.id, data: [{ score: current.score, source: current.source }] });
}
else {
existingArr[0].data.push({ score: current.score, source: current.source });
}
return acc;
}, newData);
This version uses groupBy to group the items by id and then maps across each grouping to create the required object:
var groupToItem = function(items){
return {
id: items[0].id,
name: items[0].name,
data: _.map(items, function(item){
return _.pick(item, 'score', 'source');
})
}
}
var result = _.chain(data)
.groupBy('id')
.map(groupToItem)
.value();
Plain Javascript solution, only working for your specific data structure though:
function groupObjectsById(array){
var output = [];
var ids = [];
for(var i = 0; i < array.length; i++){
var current = array[i];
if(ids.indexOf(current.id) > -1){
var objInOutput = output.filter(function(obj){
if(obj.id === current.id){
return obj;
}
})[0];
var dataObj = { score: current.score, source: current.source};
objInOutput.data.push(dataObj);
}else{
var outputObject = {name: current.name, id: current.id};
outputObject.data = [{ score: current.score, source: current.source}];
output.push(outputObject);
ids.push(current.id);
}
}
return output;
}