I have an array with many objects like this:
"title": "Harry Potter and the Philosophers Stone",
"price": "7.99",
"image": "https://say-hi.me/wp-content/uploads/2015/12/Digital-Harry-Potter-1.jpg",
"id": 1,
"author": "J.K.Rowling",
"rating": 5,
"onTop": false
Some of these objects have onTop key with value true. So how i can show objects using method map ONLY with value true ?
that ?
const data =
[ { title: 'Harry Potter and the Philosophers Stone'
, price: '7.99'
, image: 'https://say-hi.me/wp-content/uploads/2015/12/Digital-Harry-Potter-1.jpg'
, id: 1
, author: 'J.K.Rowling'
, rating: 5
, onTop: false
}
, { title: 'xyz'
, price: '7.99'
, image: 'https://xyz.jpg'
, id: 1
, author: 'xyz'
, rating: 5
, onTop: true
}
]
const res = data.filter(e=>e.onTop)
console.log( res )
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use the lodash library here https://lodash.com/docs/4.17.15#filter
Then you can do
var books = [
{ 'title': 'doggo', 'onTop': true },
{ 'title': 'catto', 'onTop': false }
];
const onTopBooks = _.filter(books, function(o) { return o.onTop; });
which should return you a new array with
[{ title: 'doggo', onTop: true }]
I would not use the map method because it returns a value for each element in the array and you would need an additional loop to remove the null items you dont want. filter or some method similar like select will be better here.
Additionally, you could just do something even more basic like:
let onTopBooks = []
books.forEach( book => {
if (book.onTop) {
onTopBooks.push(book)
}
})
return onTopBooks
Related
I have a JSON from an API with this content:
"items":[
{
id: *id here*,
variant: {
variant_name: *name here*,
variant_id: *id here*,
stores: {
0:
store_id: *STOREID1*,
available_for_sale: true
1:
store_id: *STOREID2*,
available_for_sale: true
}
}
}]
I want to select the items with the same store ID and Available for sale status. I have tried this but this isn't working:
if(items.variant.stores.store_id === "STOREID1" && items.variant.stores.available_for_sale === 'true'){
But it says
Uncaught TypeError: Cannot read property 'store_id' of undefined
EDIT:
I tried this:
if(items.variants.stores.store_id["******"] && items.variants.stores.available_for_sale['true']){
But it still gives the same error.
EDIT 2:
Edited the Question for more clarification.
Your JSON file is malformed. I've tried to fix it to be valid. Next time take the object you get in the console.log, and instead use JSON.stringify(jsobject) for valid JSON output instead of trying to copy paste it verbatim.
It's not entirely clear if you want the whole object, or just the stores values. But I've implemented both.
I've used Object.values, because your notation looks like objects (which would make it invalid JSON), but if they are really arrays, you shouldn't need Object.values.
data = {
"items": [{
id: "*id here*",
variant: {
variant_name: "*name here*",
variant_id: "*id here*",
stores: {
0: {
store_id: "*STOREID1*",
available_for_sale: true
},
1: {
store_id: "*STOREID2*",
available_for_sale: true
}
}
}
}]
}
// filter for and return whole object for any that have the stores in question
// use some to to search for at least one match of store values
console.log(
data.items.filter(item => Object.values(item.variant.stores).some(({
store_id,
available_for_sale
}) => store_id === '*STOREID1*' && available_for_sale))
)
// get stores values
// Using flatMap to combine all the arrays returned from each stores object.
console.log(
data.items.flatMap(item => Object.values(item.variant.stores).filter(({
store_id,
available_for_sale
}) => store_id === '*STOREID1*' && available_for_sale))
)
items is an array, you need to iterate over it and filter the items you want
const items = [{
id: 1,
variant: {
variant_name: '*name here*',
variant_id: 111,
stores: { store_id: 1111, available_for_sale: true }
}
},
{
id: 2,
variant: {
variant_name: 'name here',
variant_id: 222,
stores: { store_id: 2222, available_for_sale: true }
}
}
];
const result = items.filter(({variant: v}) => (
v.stores.store_id === 2222 && v.stores.available_for_sale
));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have this set of data that I'm trying to convert to map:
x = [
{
food: 'Steak',
ingredients: [
{
item1: 'pepper',
},
{
item2: "salt",
},
],
},
{
food: 'Veggies'
},
{
food: 'Fruits'
},
];
This is my current map function, question is how do I iterate on the ingredients?:
<div>
{Object.keys(x).map(key => (
<a key={key}>{x[key].food}</a>
))}
</div>
Something like this?
x = [
{
food: 'Steak',
ingredients: [
{
item1: 'pepper',
},
{
item2: "salt",
},
],
},
{
food: 'Veggies'
},
{
food: 'Fruits'
},
];
const list = x.map(item =>
({[item.food]: item.ingredients ?
item.ingredients.flatMap(i =>
Object.keys(i).map(k =>
i[k])).join(','): 'no ingredients'}))
console.log(list)
Output:
[
{
"Steak": "pepper,salt"
},
{
"Veggies": "no ingredients"
},
{
"Fruits": "no ingredients"
}
]
A better format for the data:
x = [
{
food: 'Steak',
ingredients: [
"pepper", "salt",
],
},
{
food: 'Veggies'
},
{
food: 'Fruits'
},
];
Naming things is 80% of programming. The other 20% is choosing the right font for your IDE.
If you have an array of objects and the key of object holds no semantic meaning, and there is one key in each object, that's a sign that it should be an array.
You could go one step further:
const ingredients = {
Steak: ["pepper", "salt"],
Veggies: []
Fruits: []
};
The name of the data structure makes sense. It is an "ingredients by food" object.
Where you went off is starting with x as the name of the object. x is an unknown. Start by describing everything clearly, and use JetBrains Mono.
If you want to easily iterate over the object using map (like to render a table in React), then you could do:
const ingredients = [
{Steak: ["pepper", "salt"]},
{Veggies: []},
{Fruits: []}
];
or:
const recipes = [
{food: Steak, ingredients: ["pepper", "salt"]},
{food: Veggies, ingredients: []},
{food: Fruits, ingredients: []}
];
(which is close to the reduction I did to your original data)
That one should be called recipes, which I discovered when I wrote this next function and the names didn't make sense if the object were named ingredients.
recipes.forEach(recipe => {
console.log(`HTML Title: %{recipe.food})
console.log(`HTML Subtitle: Ingredients`)
recipe.ingredients.forEach(ingredient =>
console.log(`* ${ingredient}`)
)
})
See, the names in the data structure make sense, and so do the functions to work with it. And the data structure itself is small and comprehensible. Structure is also data.
JetBrains Mono.
You can store all ingredientItem in one array and then apply Map on that array:
let ingredientItem = [];
x.forEach((item) => {
if (item.ingredients) {
item.ingredients.forEach((ingredient) => {
for (name in ingredient) {
ingredientItem.push(ingredient[name])
}
})
}
})
ingredientItem.map((item) => {
})
My question is, how can i access each object inside an Array? or
perhaps, how am I supposed to solve this problem? Like I know in head,
i have to compare categories and then push into new const array that
category. So far, i get each object in array wrote down, but I need to
do an push method after category is same, and also after that to
splice the category from each object.
My solution so far:
export const convert = inside => {
inside(({id,name,category}) => {
outside[category].push({id,name});
});
console.log(outside);
return outside;
}
Sorry for messed code, could not load here.
You could take the category as key for the object and push a new object.
No need for an array for every category, because this appoach uses the result object with dynamic keys.
const
inside = [{ id: 1, name: "orange", category: "fruits" }, { id: 2, name: "apple", category: "fruits" }, { id: 3, name: "carrot", category: "vegetable" }],
outside = {};
inside.forEach(({ id, name, category }) => {
outside[category] = outside[category] || [];
outside[category].push({ id, name });
});
console.log(outside);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I'm not fully sure i understand the question but from what i think is needed, you want to take all the items from the outside constant and take their respective category, apply it to the food Object and then add that Object to the inside variable.
const outside = {
fruits: [{
id: 1,
name: "orange"
}, {
id: 2,
name: "apple"
}],
vegetable: [{
id: 3,
name: "carrot"
}]
}
const categories = Object.keys(outside)
let inside = []
categories.forEach(category => {
const categorizedFood = outside[category].map(f => ({...f, category }) )
inside = [...inside, ...categorizedFood]
})
console.log(inside)
.as-console-wrapper {
background: #FFF;
filter: invert(1) hue-rotate(210deg);
}
I am trying to use Lodash to filter an array of objects based on a match of id's, this is what I have tried:
var team = _.find(this.teams, { 'id': this.newSchedule.team});
_.filter(this.yards, function(yard) {
return _.find(team.yards, { id: yard.id });
});
yards data:
[ { "id": 1, "name": "Test" },{ "id": 2, "name": "Test 2" } ]
team data:
[ { "id": 1, "name": "Team 1", "yards": [{ "id": 1, "name" }] ]
I want this.yards to show the yards based on the yard id from a selected team.
Its hard to understand what you mean, does the yard id match the team id?
If so it sounds like what you need to do is first find the team with the same id then grab that teams yards. Therefore I would use the map function twice:
const result = this
.yards
.map(y => team.find(t => t.id === y.id)) // join with the right team
.map(t => t.yards) // reduce to that teams yards
As team is an array, you need to iterate it before doing the _.find on an individual element in that array. It doesn't help that you called your variable team (singular). teams would make more sense.
Here is how you would change your lodash code:
var yards = [ { id: 1, name: "Test" },{ id: 2, name: "Test 2" } ],
teams = [ { id: 1, name: "Team 1", yards: [{ id: 1, name: "Missing string" }] } ]
result = _.filter(this.yards, function(yard) {
return _.some(this.teams, function(team) {
return _.find(team.yards, { id: yard.id });
});
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>
So this returns the yards that are related to at least one team.
So for example I have a MAIN array with all the information I need:
$scope.songs = [
{ title: 'Reggae', url:"#/app/mworkouts", id: 1 },
{ title: 'Chill', url:"#/app/browse", id: 2 },
{ title: 'Dubstep', url:"#/app/search", id: 3 },
{ title: 'Indie', url:"#/app/search", id: 4 },
{ title: 'Rap', url:"#/app/mworkouts", id: 5 },
{ title: 'Cowbell', url:"#/app/mworkouts", id: 6 }
];
I want to put only certain objects into another array without typing in each of the objects so the end result will look like
$scope.array1 = [
{ title: 'Reggae', url:"#/app/mworkouts",id: 1 },
{ title: 'Cowbell', url:"#/app/mworkouts",id: 6 }
];
I have tried this with no luck:
$scope.array1 = [
{ $scope.songs[1] },
{ $scope.songs[6] }
];
I will have to do a bunch of these so typing in each object would take forever, is there any faster way to do this? Thanks in advance :)
You need to do something like this:
$scope.array1 = $scope.songs.filter(function (song) {
return (song.title == "Reggae" || song.title == "Cowbell");
});
Here, the filter function will give you a filtered new array to be replaced for the original scope value.
Or in simple way, using the array indices, you can use:
$scope.array1 = [ $scope.songs[0] , $scope.songs[5] ];
You need to remove the braces since it's already an object. Although the array index starts from 0 so change index value based on 0.
$scope.array1 = [
$scope.songs[0] ,
$scope.songs[5]
];