Trying to return a filter() value from an array of objects based on conditionals - javascript

I'm trying to return only a part of my object as an array based on conditionals but I'm kinda stumped.
I have an array of objects and I want to return an array of names for each key : value they fit in.
I do get only the unique pairings but I'm returning the food key:value as well and all of it is still inside an object not a new array. Some insight would be greatly appreciated. Newer to coding.
const organizeNames = function (foods) {
let foodNames = foods.filter((names) => {
if (names.food === 'oranges') {
return names.name;
}
});
console.log(foodNames);
};
console.log(
organizeNames([
{ name: 'Samuel', food: 'oranges' },
{ name: 'Victoria', food: 'pizza' },
{ name: 'Karim', food: 'pizza' },
{ name: 'Donald', food: 'pizza' },
])
);

You're really close here. What you need to incorporate is .map() to map your list of objects to a list of names. Your filter part works, partly by accident, so I've fixed it to be more correct (return names.food === 'oranges'), and then once you have your list of objects that match 'oranges' for their food, you map that filtered list into a list of names by doing .map(names => names.name)
const organizeNames = function (foods) {
let foodNames = foods.filter((names) => {
// only keep items whose .food property === 'oranges'
return names.food === 'oranges'; // returns true or false
}).map(names => {
// map the filtered list of objects into a list of names by
// returning just the object's .name property
return names.name;
});
return foodNames;
};
console.log(
organizeNames([
{ name: 'Samuel', food: 'oranges' },
{ name: 'Victoria', food: 'pizza' },
{ name: 'Karim', food: 'pizza' },
{ name: 'Donald', food: 'pizza' },
])
);

The filter() callback function should just return true or false. Then you can use map() to get a specific property from each of the filtered items.
const organizeNames = function(foods) {
let foodNames = foods.filter((names) => names.food == 'oranges').map(names => names.name);
return foodNames;
}
console.log(
organizeNames([{
name: 'Samuel',
food: 'oranges'
},
{
name: 'Victoria',
food: 'pizza'
},
{
name: 'Karim',
food: 'pizza'
},
{
name: 'Donald',
food: 'pizza'
},
])
);

Related

Filter array of objects by value

I want to filter an array of objects, by a specific value within the objects.
In the example i've provided I want to filter the array 'pets' by a value in the array 'characteristics'. For example, where I have called the function with the param 'loyal', i'd only expect the object for the dog value to be returned, as only the dog has that characteristic.
At the moment when I call the function both objects are returned even though only the object for dog has that value in its characteristics array.
const pets = [
{
name: 'dog',
characteristics: [
{
value: 'loyal'
},
{
value: 'big'
}
]
},
{
name: 'cat',
characteristics: [
{
value: 'fluffy'
},
{
value: 'small'
}
]
},
]
function filterPets(pets, characteristic) {
return pets.filter(function(pet) {
return pet.characteristics.filter(o => o.value.includes(characteristic));
})
}
console.log(filterPets(pets, 'loyal'));
That's because for the characteristics check you're using filter, which always returns an array (even if a blank one), and even a blank array is a truthy value, so the outer filter keeps every pet you check. For that inner check, you want some, not filter, so you get a flag for whether any entries matched:
function filterPets(pets, characteristic) {
return pets.filter(function(pet) {
return pet.characteristics.some(o => o.value.includes(characteristic));
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^
});
}
const pets = [
{
name: 'dog',
characteristics: [
{
value: 'loyal'
},
{
value: 'big'
}
]
},
{
name: 'cat',
characteristics: [
{
value: 'fluffy'
},
{
value: 'small'
}
]
},
];
function filterPets(pets, characteristic) {
return pets.filter(function(pet) {
return pet.characteristics.some(o => o.value.includes(characteristic));
});
}
console.log(filterPets(pets, 'loyal'));
Just for what it's worth, I assume characteristics are unique (you can't have "loyal" twice), so you might prefer to keep those in a Set so you can check for them more easily than .some(o => o.includes(characteristic)). For instance:
const pets = [
{
name: "dog",
characteristics: new Set(["loyal", "big"]),
},
{
name: "cat",
characteristics: new Set(["fluffy", "small"]),
},
];
function filterPets(pets, characteristic) {
return pets.filter(function(pet) {
return pet.characteristics.has(characteristic);
});
}
Live Example:
const pets = [
{
name: "dog",
characteristics: new Set(["loyal", "big"]),
},
{
name: "cat",
characteristics: new Set(["fluffy", "small"]),
},
];
function filterPets(pets, characteristic) {
return pets.filter(function(pet) {
return pet.characteristics.has(characteristic);
});
}
console.log(filterPets(pets, "loyal"));
console.log("Don't worry about the {} for characteristics, the Stack Snippets console doesn't know how to display Set objects. Look in the real console if you want to double-check the set.");
function filterPets(list, charValue) {
const filteredPets = []
list.map(function(pet,petIndex,array) {
pet.characteristics.map(function(charac){
if(charac.value === charValue){
return filteredPets.push(array[petIndex])
}
})
})
return filteredPets
}
filterPets(pets,'loyal');

Taking JSON values in a response and mapping them to a state object with keys?

[Noob to Javascript and React] I am using an API that returns an object with values like this. AAPL, AMZN, FB, GOOGL, can be anything based on the function's string array input.
{
AAPL: { price: 329.99 },
AMZN: { price: 2563.05 },
FB: { price: 239.93 },
GOOGL: { price: 1469.12 }
}
How could I consider dynamically mapping a response like this into a state object like this? The id property doesn't exist, it needs to be created.
state = {
stocks: [ { id: 1, name: 'AAPL', price: 329.99 }, { id: 2, name: 'AMZN', price: 2563.05 }, ...]
}
I'm able to successfully print the stock names and their prices separately but I am having trouble figuring out how I could wire them into a state object like what's above.
function getCurrentPriceOfBatchStocks(_stocks) {
iex
.symbols(_stocks)
.price()
.then(res => {
console.log(typeof res);
console.log(res);
console.log(Object.keys(res));
console.log(Object.values(res));
});
}
Not sure where you're getting id from, so I'm using idx as an example.
const stocks = Object.keys(resp).map((key, idx) => ({ id: idx + 1, name: key, price: resp[key] }))
Here is an implementation. With Object.entries, you get an array with an array of [key, value] of your original object. And you can map this array to a different format.
You can check the result with the Run code snippet button.
let st = {
AAPL: { price: 329.99 },
AMZN: { price: 2563.05 },
FB: { price: 239.93 },
GOOGL: { price: 1469.12 }
}
let stocks = Object.entries(st).map(([key, value], index) => ({id: index + 1, name: key, price: value.price}))
console.log(stocks)
const res={
AAPL: { price: 329.99 },
AMZN: { price: 2563.05 },
FB: { price: 239.93 },
GOOGL: { price: 1469.12 }
}
console.log(Object.entries(res).map((entry,index)=>{
return {
id:index+1,
name:entry[0],
...entry[1]
}
}));

how do i create a new object based off an array and another object?

I am trying to create a new object based off an existing array. I want to create a new object that show below
{ jack: 'jack', content: 'ocean'},
{ marie: 'marie', content: 'pond'},
{ james: 'james', content: 'fish biscuit'},
{paul: 'paul', content: 'cake'}
const words = ['jack','marie','james','paul']
const myUsers = [
{ name: 'jack', likes: 'ocean' },
{ name: 'marie', likes: 'pond' },
{ name: 'james', likes: 'fish biscuits' },
{ name: 'paul', likes: 'cake' }
]
const usersByLikes = words.map(word => {
const container = {};
container[word] = myUsers.map(user => user.name);
container.content = myUsers[0].likes;
return container;
})
I am not getting the correct object, but instead it returns a list.
[ { jack: [ 'shark', 'turtle', 'otter' ], content: 'ocean'}, { marie: [ 'shark', 'turtle', 'otter' ], content: 'ocean' },
{ james: [ 'shark', 'turtle', 'otter' ], content: 'ocean' },
{ paul: [ 'shark', 'turtle', 'otter' ], content: 'ocean'} ]
What is the role of words array? I think the below code will work.
const result = myUsers.map(user => ({
[user.name]: user.name,
content: user.likes
}));
console.log('result', result);
In case, if want to filter the users in word array then below solution will work for you.
const result = myUsers.filter(user => {
if (words.includes(user.name)) {
return ({
[user.name]: user.name,
content: user.likes
})
}
return false;
});
You can achieve your need with a single loop.
The answer #aravindan-venkatesan gave should give you the result you are looking for. However important to consider:
When using .map() javascript returns an array of the same length, with whatever transformations you told it to inside map().
If you want to create a brand new object, of your own construction. Try using .reduce(). This allows you to set an input variable, i.e: object, array or string.
Then loop over, and return exactly what you want, not a mapped version of the old array.
See here for more details:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

how to loop through multiple arrays inside an array and filter a value from it-Javascript

I'm using EXTJS framework for my code.
below is my array structure:
data = [{
id: 22,
rows: [{
id: "673627",
name: "ABS",
address: "536street"
}, {
id: "333",
name: "TEST$$",
address: "536street"
}, {
id: "999",
name: "TEST$$",
address: "536street"
}]
}, {
id: 33,
rows: [{
id: "899",
name: "TES",
address: "536street"
}, {
id: "333",
name: "TEST$$",
address: "536street"
}, {
id: "999",
name: "TES673",
address: "536street"
}]
}]
Now I want to filter the name from this array, whose value I'm comparing with say "TEST$$".
I'm doing this;
Ext.each(data, function(item) {
filter = item.rows.filter(function(name) {
return name.name === "TEST$$";
}, this);
}, this);
console.log(filter);
In this case, it returns only 1 match, where as I have 3 matches for this particular value. It returns the match from the last item in the data array and hence I dont get all the matching values, any idea how this can be looped to get all values matching?
thx!
You're reassigning the filter variable on every iteration over the data array:
filter = item.rows.filter(function(name) {
return name.name === "TEST$$";
}, this);
On the last iteration, there is only one match, the one with id of 333, so that's the only one that you see after running the Ext.each. Try pushing to an external array that doesn't get overwritten instead:
const testItems = [];
Ext.each(data, function(item) {
const filtered = item.rows.filter(row => row.name === "TEST$$")
testItems.push(...filtered);
});
console.log(testItems);
Note that there's no need to pass along the this context.
Another option is to flatMap to extract all rows to a single array first:
const output = data
.flatMap(({ rows }) => rows)
.filter(({ name }) => name === 'TEST$$');

How to build tree array from flat array of object with category and subCategrie properties

I am trying to build tree array from flat array, each item in the flat array has two property need to be used to build the tree array, they are 1. category. 2. subCategrie which is array of string.
let data = [
{
id: 1,
name: "Zend",
category: "php",
subCategory: ["framework"]
},
{
id: 2,
name: "Laravel",
category: "php",
subCategory: ["framework"]
},
{
id: 3,
name: "Vesion 5",
category: "php",
subCategory: ["versions"]
},
{
id: 4,
name: "Angular",
category: "frontend",
subCategory: ["framework", "typescript"]
},
{
id: 5,
name: "Aurelia",
category: "frontend",
subCategory: ["framework", "typescript"]
},
{
id: 6,
name: "JQuery",
category: "frontend",
subCategory: []
}
];
It should be
let tree = [
{
name: "php",
children: [
{
name: "framework",
children: [
{
id: 1,
name: "Zend"
},
{
id: 2,
name: "Laravel"
}
]
},
{
name: "versions",
children: [
{
id: 3,
name: "Vesion 5"
}
]
}
]
}
// ...
];
Is there any article, link solving similar problem?
I gave it many tries but stuck when trying to build the sub categories children.
Here's my last attempt which throws error and I know it's wrong but it's for the ones who want to see my attempts
const list = require('./filter.json')
let tree = {};
for (let filter of list) {
if (tree[filter.category]) {
tree[filter.category].push(filter);
} else {
tree[filter.category] = [filter];
}
}
function buildChildren(list, subcategories, category, index) {
let tree = {}
for (let filter of list) {
if (filter.subcategory.length) {
for (let i = 0; i < filter.subcategory.length; i++) {
let branch = list.filter(item => item.subcategory[i] === filter.subcategory[i]);
branch.forEach(item =>{
if (tree[filter.subcategory[i]]){
tree[filter.subcategory[i]] = tree[filter.subcategory[i]].push(item)
}else{
tree[item.subcategory[i]] = [item]
}
})
}
}
}
console.log('tree ', tree);
}
Heads up, For javascript I usually use Lodash (usually written as _ in code) but most of these methods should also be built in to the objects in javascript (i.e. _.forEach = Array.forEach())
const tree = [];
// First Group all elements of the same category (PHP, Frontend, etc.)
data = _.groupBy(data, 'category');
_.forEach(data, function (categoryElements, categoryName) {
// Each Category will have it's own subCategories that we will want to handle
let categorySubCategories = {};
// The categoryElements will be an array of all the objects in a given category (php / frontend / etc..)
categoryElements.map(function (element) {
// For each of these categoryies, we will want to grab the subcategories they belong to
element.subCategory.map(function (subCategoryName) {
// Check if teh category (PHP) already has already started a group of this subcategory,
// else initialize it as an empty list
if (!categorySubCategories[subCategoryName]) { categorySubCategories[subCategoryName] = []; }
// Push this element into the subcategory list
categorySubCategories[subCategoryName].push({id: element.id, name: element.name});
});
});
// Create a category map, which will be a list in the format {name, children}, created from
// our categorySubCategories object, which is in the format {name: children}
let categoryMap = [];
_.forEach(categorySubCategories, function (subCategoryElements, subCategoryName) {
categoryMap.push({name: subCategoryName, children: subCategoryElements});
});
// Now that we've grouped the sub categories, just give the tree it's category name and children
tree.push({name: categoryName, children: categoryMap});
});
};
The key to success here is to create an interim format that allows for easy lookups. Because you work with children arrays, you end up having to use filter and find whenever you add something new, to prevent duplicates and ensure grouping.
By working with a format based on objects and keys, it's much easier to do the grouping.
We can create the groups in a single nested loop, which means we only touch each item once for the main logic. The group has this format:
{ "categoryName": { "subCategoryName": [ { id, name } ] } }
Then, getting to the required { name, children } format is a matter of one more loop over the entries of this tree. In this loop we move from { "categoryName": catData } to { name: "categoryName", children: catData }
Here's an example that shows the two steps separately:
const data=[{id:1,name:"Zend",category:"php",subCategory:["framework"]},{id:2,name:"Laravel",category:"php",subCategory:["framework"]},{id:3,name:"Vesion 5",category:"php",subCategory:["versions"]},{id:4,name:"Angular",category:"frontend",subCategory:["framework","typescript"]},{id:5,name:"Aurelia",category:"frontend",subCategory:["framework","typescript"]},{id:6,name:"JQuery",category:"frontend",subCategory:[]}];
// { category: { subCategory: [ items ] } }
const categoryOverview = data.reduce(
(acc, { id, name, category, subCategory }) => {
// Create a top level group if there isn't one yet
if (!acc[category]) acc[category] = {};
subCategory.forEach(sc => {
// Create an array for this subCat if there isn't one yet
acc[category][sc] = (acc[category][sc] || [])
// and add the current item to it
.concat({ id, name });
});
return acc;
},
{}
)
const nameChildrenMap = Object
.entries(categoryOverview)
// Create top level { name, children } objects
.map(([cat, subCats]) => ({
name: cat,
children: Object
.entries(subCats)
// Create sub level { name, children } objects
.map(([subCat, items]) => ({
name: subCat,
children: items
}))
}))
console.log(nameChildrenMap);

Categories

Resources