I am fairly new to Vue and JS but I am making API calls and getting a JSON response then sending the response to an empty array. How do I get the ID of each object in the array?
The array that the response is being pushed to is structured like this
groups: [
{
"id": "0",
"name": "a",
"price": 5
},
{
"id": "1",
"name": "b",
"price": 5
},
{
"id": "2",
"name": "c",
"price": 5
}
]
I'd like to pull the Id of each object and push the values to an empty array
for(var group in this.groups) {
if (this.groups.hasOwnProperty(0)) {
this.group = this.groups[0];
this.groupsId.push(this.innerObj);
}
}
The error I'm getting is saying Cannot read property '0' of undefined at eval
Ideally I'd like an array that has all the Ids of each object.
this.groups.hasOwnProperty(0) should be group.hasOwnProperty('id')
Use Array.prototype.map() to iterate over an array of objects and collect every ID into a new array:
const res = {
groups: [{
"id": "0",
"name": "a",
"price": 5
},
{
"id": "1",
"name": "b",
"price": 5
},
{
"id": "2",
"name": "c",
"price": 5
}
]
};
const ids = res.groups.map(obj => { // you use this.groups
if(obj.hasOwnProperty('id')) return obj.id;
});
console.log(ids)
There is the Array.map() method:
this.groupsId = this.groups.map(i => i.id);
If you already have elements in this.groupsId you can append the ids using Array.concat():
this.groupsId = this.groupsId.concat(this.groups.map(i => i.id));
You can use Array.prototype.reduce to loop and check if there's id.
const groups = [
{"name": "a","price": 5},
{"id": "1","name": "b","price": 5},
{ "id": "2","name": "c","price": 5}
];
const list = groups.reduce((groupIds, group) => group.id ? [...groupIds, group.id] : groupIds, []);
console.log(list);
Related
I'm trying to filter some objects based on another array of objects. So I'm getting data from an API. These are for example receipts:
[
{
"id": 1,
"name": "test",
"category": {
"id": 1,
"name": "Cookies",
},
},
{
"id": 2,
"name": "test2",
"category": {
"id": 2,
"name": "Candy",
},
}
]
Then I'm trying to filter the objects on the category name based on another array of categories.
I've created a function for this:
function onSelectCategory(category) {
let receiptsList = receipts.filter((a) =>
a.category.includes(category.name)
);
setReceiptsView(receiptsList);
setSelectedCategory(category);
}
const category = [ { "id": 2, "name": "Candy" } ];
onSelectCategory(category);
When I run this function, I get an empty Array []. I can't really figure out what I'm doing wrong.
Since the param seems to be an array of objects, you need to use Array#some for comparison instead:
const receipts = [
{ "id": 1, "name": "test", "category": { "id": 1, "name": "Cookies" } },
{ "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];
const receiptsList = receipts.filter(({ category }) =>
categories.some(({ name }) => name === category.name)
);
console.log(receiptsList);
Another solution using Set:
const receipts = [
{ "id": 1, "name": "test", "category": { "id": 1, "name": "Cookies" } },
{ "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];
const categorySet = new Set(categories.map(({ name }) => name));
const receiptsList = receipts.filter(({ category }) =>
categorySet.has(category.name)
);
console.log(receiptsList);
Assuming that category (the parameter) is a string, the issue is that you are attempting to get the attribute name from the string, when you should be comparing the string to the object.
Try this:
a.category.name == category;
instead of
a.category.includes(category.name)
I may be wrong aboout assuming that category is a string, please clarify by telling us what the parameter category is equal to.
I am working on an angular application. I have to read data from json and process in two parts.
Read data from json using express: I have following Json in alphabetically sorted order.
{
"1": "Andy",
"2": "Billy"
"3": "Carry"
"4": "Doda"
}
Left hand side are Id's and Right one's are names. I have to read this data using express and access this data in my angular component.
In my angular component I have another array which is also sorted. That array is as follows:
[
{
"Name": "Andy",
"Id": "1"
"IncomingTime": "2020-06-19T11:02+00:00",
"Outgoingtime": "2020-06-19T11:07+00:00"
},
{
"Name": "Billy",
"Id": "2"
"IncomingTime": "2020-06-19T11:05+00:00",
"Outgoingtime": "2020-06-19T11:17+00:00"
},
{
"Name": "Ciena",
"Id": 5
"IncomingTime": "2020-06-19T11:05+00:00",
"Outgoingtime": "2020-06-19T11:07+00:00"
},
{
"Name": "Doda",
"Id": "4"
"IncomingTime": "2020-06-19T11:05+00:00",
"Outgoingtime": "2020-06-19T11:07+00:00"
}
]
Once above Json data is available in component(JSON in point 1), I have to make a new array(or any data structure which can be sorted). In that new array I have to put data in such a way that alphabetically sorted "Name" coming from above Json should match with with data in sorted array. If Name is matched then content(Name, id, IncomingTime , OutgoingTime) is copied to new array for that particular "Name" which will also be sorted. If suppose While comparing names we came across a name for which data is not there in sorted array, we need to keep only Name in new array doesn't matter data is there or not. Like in above data for "Carry" data is not there in sorted array still in final array "Carry" should be there. How can I do that?
You can do it using Lodash. Lodash provides functions to achieve what you want. documentation is here.
install Lodash from here.
import Lodash import * as _ from 'lodash';
I think this is what you want
const arr = { 1: 'Andy', 2: 'Billy', 3: 'Carry', 4: 'Doda' };
const data = [
{
"Name": "Andy",
"Id": "1",
"IncomingTime": "2020-06-19T11:02+00:00",
"Outgoingtime": "2020-06-19T11:07+00:00"
},
{
"Name": "Billy",
"Id": "2",
"IncomingTime": "2020-06-19T11:05+00:00",
"Outgoingtime": "2020-06-19T11:17+00:00"
},
{
"Name": "Ciena",
"Id": 5,
"IncomingTime": "2020-06-19T11:05+00:00",
"Outgoingtime": "2020-06-19T11:07+00:00"
},
{
"Name": "Doda",
"Id": "4",
"IncomingTime": "2020-06-19T11:05+00:00",
"Outgoingtime": "2020-06-19T11:07+00:00"
}
];
const newArray = _.map(arr, item => {
const value = _.find(data, ['Name', item]);
const obj = value ? value : {Name: item};
return obj;
});
console.log(newArray);
Considering below object array:
[
{
"guid": "j5Dc9Z",
"courses": [
{
"id": 1,
"name": "foo",
}
]
},
{
"guid": "a5gdfS",
"courses": [
{
"id": 2,
"name": "bar",
},
{
"id": 3,
"name": "foo",
},
]
},
{
"guid": "jHab6i",
"courses": [
{
"id": 4,
"name": "foobar",
}
]
},
{...}
]
I am trying to filter an object array, comparing IDs in the nested courses array with in the below array:
filter.courses = [1,3]
The following line works for the nth value in the array: (via https://stackoverflow.com/a/41347441/9766768)
let fil = filter(this.results, { courses: [{ id: this.filter.courses[n] }]});
However, I'm hoping to achieve this (pseudo code below):
let fil = filter(this.results, { courses: [{ id: this.filter.courses }]});
Expected output would be an array of objects containing any of the course IDs elements, in this case:
[
{
"guid": "j5Dc9Z",
"courses": [
{
"id": 1,
"name": "foo",
}
]
},
{
"guid": "a5gdfS",
"courses": [
{
"id": 2,
"name": "bar",
},
{
"id": 3,
"name": "foo",
},
]
}
]
What would be considered the best solution in this case? Avoiding loops would be a bonus.
If you're trying to filter the elements whose course IDs contain in the filter.courses, you may use Array#every and Array#includes to do that:
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 = [1, 6, 3];
const r = data.filter(d => d.courses.every(c => courses.includes(c.id)));
console.log(r);
try this,
results = [
{
"guid": "j5Dc9Z",
"courses": [
{
"id": 3,
"name": "foo",
}
]
},
{
"guid": "a5gdfS",
"courses": [
{
"id": 1,
"name": "bar",
},
{
"id": 3,
"name": "foo",
},
]
}
]
var filter = [1]
console.log(results.map(result=>{
result.courses = result.courses.filter(course=>(filter.includes(course.id)))
return result
}))
Explore my recursive solution there: Playground Link
With this solution can nested array of objects being filtered from top level to botton level, layer by layer.
From what I understand the resulting array should contain all objects, that contain at least one course with an id that is contained in the array we use to filter.
So if an object exists with 2 courses - and one of them has an id we are looking for this object should then be part of the array that gets returned (see object with property "guid" : "a5gdfS" in the questions example)
With one little tweak the code provided in the answer by 31piy (marked as best by question owner) will do exactly what we desire. To do so we just change the array method every() to the array method some().
const r = data.filter(d => d.courses.every(c => courses.includes(c.id)));
const r = data.filter(d => d.courses.some(c => courses.includes(c.id)));
With the method every() the resulting array will only contain the objects, where each and every course has an id we are looking for. ("guid": "a5gdfS" is not in the resulting array)
With the method some() the resulting array will contain the objects, where at least one course has an id we are looking for ("guid": "a5gdfS" is in the resulting array)
/* arrays are the same as provided in the question
so that we can check against expected/desired output in the question */
const data = [{
"guid": "j5Dc9Z",
"courses": [{
"id": 1,
"name": "foo",
}]
},
{
"guid": "a5gdfS",
"courses": [{
"id": 2,
"name": "bar",
},
{
"id": 3,
"name": "foo",
},
]
},
{
"guid": "jHab6i",
"courses": [{
"id": 4,
"name": "foobar",
}]
}
];
const courses = [1, 3];
//array contains all objects with at least 1 course that has an id we are looking for
const r = data.filter(d => d.courses.some(c => courses.includes(c.id)));
console.log("code with some " + JSON.stringify(r));
//array contains only objects, whose classes all have an id we are looking for
const o = data.filter(d => d.courses.every(c => courses.includes(c.id)));
console.log("code with every " + JSON.stringify(o));
depending on what we are trying to do either every() or some() might be correct - depends on what we are trying to achieve
This question already has answers here:
Sort array containing objects based on another array [duplicate]
(2 answers)
Closed 4 years ago.
Sort one array based on another array when second array is the key in first array.
Lets say I have a main array like below:
let mainArray = [{ "id": 24443, "name": "Apple" }, { "id": 20172, "name": "Banana" }, { "id": 187016, "name": "Cherry" }, { "id": 217632, "name": "Guava" }, { "id": 5221, "name": "Peach" }, { "id": 97568, "name": "Strawberry" }]
And I have id array like below:
let idArray = [ "24443", "20172", "5221", "187016", "217632", "97568" ]
Notice that second array contains values which are "id" property in the first array.
What are the best ways to sort the main array based on the order of occurrence of "key" in the second array?
If you are not absolutely after performance, here is a simple way of doing it:
mainArray.sort( (a,b) => idArray.indexOf(a.id.toString()) - idArray.indexOf(b.id.toString()));
Or for linear algorithm (parse both vectors only once):
// Array to Map
let map = mainArray.reduce( (acc, {id,name}) => Object.assign(acc, {[id] : name}), {});
idArray.map( id => ({id, name: map[id]}) )
I have created a function that does map and sorting:
This function will map through the array of keys and find that key in the mainArray and return it.
var mapAndSort = (mainArr, indexArr, key) => {
if (mainArr.length != indexArr.length) {
return null;
}
return indexArr.map(val => {
return mainArr.find(c => c[key] == val);
});
}
var mainArray = [{ "id": 24443, "name": "Apple" }, { "id": 20172, "name": "Banana" }, { "id": 187016, "name": "Cherry" }, { "id": 217632, "name": "Guava" }, { "id": 5221, "name": "Peach" }, { "id": 97568, "name": "Strawberry" }];
var idArray = [ "20172","24443", "5221", "217632", "97568", "187016"];
var result = mapAndSort(mainArray, idArray, 'id');
document.write(JSON.stringify(result));
I have an array of objects. I would like to reformat into a new array but am not sure how to begin. I have jQuery and Underscore available.
Here is my original array:
var myArray = [
{
"name": "Product",
"value": "Car"
},
{
"name": "Product",
"value": "Boat"
},
{
"name": "Product",
"value": "Truck"
},
{
"name": "Color",
"value": "Blue"
},
{
"name": "Location",
"value": "Store"
}
];
Here is what I am trying to make the new Array look like:
var newArray = [
{
"name": "Product",
"value": "Car Boat Truck"
},
{
"name": "Color",
"value": "Blue"
},
{
"name": "Location",
"value": "Store"
}
];
In the newArray the Products are all in one object.
You can use the groupBy method to get all the elements with the same name together, then map to transform them into what you want. And pluck is useful here to combine the values in the output array.
Here's quick, simple solution:
var newArray = _.chain(myArray)
.groupBy("name")
.map(function(a) {
return {
"name": a[0].name,
"value": _.pluck(a, "value").join(" ")
};
})
.value();
Demonstration
And just for completeness, here's the non-chained version:
var newArray = _.map(_.groupBy(myArray, "name"), function(a) {
return {
"name": a[0].name,
"value": _.pluck(a, "value").join(" ")
};
});
Here's a more generalized solution that's reusable and not hard-coded. This way, you can create multiple groupBy methods for different properties of different object collections, then join the properties that you require. jsFiddle
function groupBy(groupBy) {
return function(source, joinOn) {
return _.each(_.groupBy(source, groupBy), function(val, key, context){
context[key] = _.pluck(val, joinOn).join(' ');
});
};
}
var groupByNameOn = groupBy('name');
console.log(groupByNameOn(arr, 'value'));