Using map in a multidimensional array Javascript - javascript

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) => {
})

Related

Functional Programming exercise I can't figure out

I've been looking at a problem for hours and failing to find a solution. I'm given an array of customer objects.
In each customer object is an array of friends.
In the array of friends is an object for each friend, containing some data, including a name key/value pair.
What I'm trying to solve for: I'm given this customers array and a customer's name. I need to create a function to find if this customer name is in any other customer's friend lists, and if so, return an array of those customer's names.
Below is a customer list. And as an example, one of the customers is Olga Newton. What the code should be doing is seeing that Olga Newton is a customer and is also in the friends lists of Regina and Jay, and should be returning an array of Regina and Jay.
I thought I could do this simply with a filter function, but because the friends list is an array with more objects, this is adding level of complexity for me I can't figure out.
Below is a customer array. The out put should be
['Regina', 'Jay']
and what I've gotten has either been
[{fullCustomerObj1}, {fullCustomerObj2}]
or
[ ]
What am I missing?
Here is the customer array:
var customers = [{
name: "Olga Newton",
age: 43,
balance: "$3,400",
friends: [{
id: 0,
name: "Justice Lara"
}, {
id: 1,
name: "Duke Patrick"
}, {
id: 2,
name: "Herring Hull"
}, {
id: 3,
name: "Johnnie Berg"
}]
}, {
name: "Regina",
age: 53,
balance: "$4,000",
friends: [{
id: 0,
name: "Cheryl Kent"
}, {
id: 1,
name: "Cynthia Wells"
}, {
id: 2,
name: "Gutierrez Waters"
}, {
id: 3,
name: "Olga Newton"
}]
}, {
name: "Jay",
age: 28,
balance: "$3,000",
friends: [{
id: 0,
name: "Cross Barnett"
}, {
id: 1,
name: "Raquel Haney"
}, {
id: 2,
name: "Olga Newton"
}, {
id: 3,
name: "Shelly Walton"
}]
}];
Use filter and map, please.
function friends(c, name){
return c.filter((a) => {
return a.friends.map(b => b.name).includes(name)
}).map(a => a.name);
}
console.log(friends(customers, "Olga Newton"));
// ['Regina', 'Jay']
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
We look to an array (friends[]) inside anther (customers[]), So used two for loops, the first determine witch customer will look for his friends, and the second the array will search inside, then set if statement if the cust name is inside friends[]: adding the customer name to customerFriends[] array, At the end return the customerFriends[].
let cust = "Olga Newton"; // Get the customer name who you look for his friends.
const findFriend = (cust, arrs) => { // Create findFriend function.
let customerFriends = []; // Create an array to set the result to it.
for (let i = 0; i < arrs.length; i++) { // For each Customer.
for (const arr of arrs[i].friends) { // For each Friend.
if (arr.name === cust) { // Use Strict equality to find Customer name in friends[].
customerFriends.push(arrs[i].name); // Add the customer name to the customerFriends[].
}
}
}
return customerFriends;// Return the final results.
}
console.log(findFriend(cust, customers)); // Call the function.

How do I put my state objects into a 2d array?

I would like to load these state objects into a 2d array. I need them in the following fashion:
[
[
"josie",
"ally",
"fred"
],
[
"edward",
"ally",
"fred",
"goolly"
]
]
I need it this way because I need a way to reference the sublist relative to the name of the sublist.
class App extends Component {
state = {
List: [
{
name: "josie",
sub: [
"ally",
"fred"
]
},
{
name: "edward",
sub: [
"ally",
"fred",
"goolly"
]
}
]
}
render() {
return (
<div>
</div>
);
}
}
export default App;
I apologize if this is too basic, but I am really beating my head on this.
One of shortest ES6 versions to implement that will be the following:
state.List.forEach(listItem => finalArr.push([].concat([listItem.name], listItem.sub)));
Here we iterate over List array and push to finalArr a new array, which we generate by merging values of name and sub object properties into one new array. And finally we have an array of arrays (each sub array generated from separate items from state.List). Here is the working example:
const state = {
List: [
{
name: "josie",
sub: [
"ally",
"fred"
]
},
{
name: "edward",
sub: [
"ally",
"fred",
"goolly"
]
}
]
}
const finalArr = [];
state.List.forEach(listItem => finalArr.push([].concat([listItem.name], listItem.sub)));
console.log(finalArr);

JavaScript - New Nested Object From Current Object Keys

When working with an object like the following, what is the most effective way to build a new object based on the current object's keys? The keys serve as the reference to where it should be in the new object - activityName1 would be equal to the first element name of the new activities nested array, activityName2 equal to the second element name of the array & so on.
const obj = {
activityName1: "Bingo",
activityName2: "Bazinga",
activityType1: "Dog",
activityType2: "Term",
description: "Games are fun.",
name: "Patty"
};
Desired object:
const newObj = {
activities: [
{name: "Bingo", type: "Dog"},
{name: "Bazinga", type: "Term"}
],
description: "Games are fun.",
name: "Patty"
};
My initial thoughts were to use reduce & Object.assign, but the building of the new object returns only a single key/value pair:
Object.keys(variables).reduce((obj, key) => {
if (key.includes('activity')) {
return Object.assign(obj, {
[key[key.length - 1]]: { activities: { [key]: variables[key] } } });
}
return obj;
}, {});
Results in a new activities array like:
[
1: {activities: {type: "Dog"},
2: {activities: {type: "Term"}
]
The only use of mapping is to look for those keys that start activityName and use those to build up your array of activities. You can reuse the key replacing activityName with activityType to get the associated type.
const obj = {
activityName1: "Bingo",
activityName2: "Bazinga",
activityType1: "Dog",
activityType2: "Term",
description: "Games are fun.",
name: "Patty"
};
var result = {
activities: Object.keys(obj).filter(k => k.startsWith("activityName")).map(k => ({
name: obj[k],
type:obj[k.replace("activityName","activityType")]
})),
description: obj.description,
name: obj.name
}
console.log(result);

Compare value and add if matches to an array

Im trying to merge 2 data sources in 1, I wanna loop through them and if a specefic value matches than add it to the first object with the same value and add the in the emty array what is already there. No matter how much objects I have.
So lets say I have this information
Source 1
one = {
"teams": [
{
name: 'ABC',
members: [],
rooms: '0'
},
{
name: 'DEF',
members: [],
rooms: '1'
}
]
}
Source 2
two = {
"persons": [
{
name: 'Foo',
gender: 'male',
room: '1'
},
{
name: 'Bar',
gender: 'female',
room: '2'
}
]
}
And what I want is that the 'persons' array merge to the members array if the 'room and rooms' value matches.
What I would assume is something similar like this:
for(var i = 0 ; i < two.persons.length; i++) {
if (one.teams[i].rooms == two.persons[i].room) {
data.teams[i].members.push(two.persons[i]);
}
}
using higher order methods you can do:
one = {
"teams": [
{
name: 'ABC',
members: [],
rooms: '0'
},
{
name: 'DEF',
members: [],
rooms: '1'
}
]
};
two = {
"persons": [
{
name: 'Foo',
gender: 'male',
room: '1'
},
{
name: 'Bar',
gender: 'female',
room: '2'
}
]
};
var ttt = one.teams.map(function(x){
var roomVal= x.rooms;
x.members = two.persons.filter(function(t){
return t.room == roomVal});
return x;
})
one.teams = ttt;
console.log(one)
The problem with your code is that once you iterate the two array, then you do not go back and see if the previous element matched with the current one.
For example, if [0] on each arrays does not match and you iterate to index [1] in the for-loop, you do not have a way to check if two[1] matched one[0].
To do a complete search, you could directly iterate the arrays for each value of two:
two.persons.forEach(function(person) {
one.teams.forEach(function(team) {
if (team.rooms == person.room) {
team.members.push(person);
}
});
});
There are many strategies to do this. But most important you should iterate each array separately. I would use an Array.forEach();
one.teams.forEach(function (team, teamsIndex, teamsArray) {
two.persons.forEach(function (person, personsIndex, personsArray) {
if (team.room == person.room) {
// Do what you need to do.
}
});
});
Didn't check syntax so be aware to read Array.forEach(); documentation.

Iterating a javascript collection and adding a sort order

I have a tree in javascript which has multiple root elements and nested children.
Here's the object:
[{
_id: '546d30905d7edd1d5169181d',
name: 'first'
children: []
}, {
_id: '546d30905d7edd1d2169181d',
name: 'second'
children: []
}, {
_id: '446d30905d7edd1d5169181d',
name: 'third',
children: [{
_id: '446d30905d7e2d1d5169181d',
name: '3child',
children: []
}, {
_id: '446d30915d7e2d1d5169181d',
name: '3child2',
children: [{
_id: '546d30905d7edd1d2569181d',
name: 'second2',
children: []
}]
}]
}, {
_id: '546d30995d7edd1d5169181d',
name: 'fourth',
children: []
}]
This is a truncated document that's being stored in MongoDB using materialized path. The issue is that I need to add a 'sorting' ability, so nodes in the same root can be sorted.
I want to iterate this tree and apply a sort_value such as node['sort_value'] = 0, etc.
Each level will have it's own sort order, starting at 0.
I can simply iterate the tree recursively:
function iterate(items) {
_.each(items, function(page, key) {
if (items.children.length > 0) {
iterate(items.children);
}
});
}
However, I can't figure out how to keep track of the sort orders and also update the object's to include the sort_value field.
Any help would be greatly appreciated! Thank you
I did it so that I used array key for sorting and "synchronized" it with object property (because I needed it saved to DB and restored after) and it works as a charm :)
So something like this, pseudo:
var unsorted = [
0:{"sort_key": "0", "data":"dataaa 0"},
1:{"sort_key": "1", "data":"dataaa 1"},
...
n:{"sort_key": "n", "data":"dataaa n"}
];
function_sort(unsorted){
...
return sorted = [
0:{"sort_key": "n", "data":"dataaa y"},
1:{"sort_key": "44", "data":"dataaa x"},
...
n:{"sort_key": "0", "data":"dataaa z"}
];
}
save = function_save(sorted){
...update sort_key as array key...
return for_saving;
}

Categories