compare array of data and assign a value - javascript

Please i want to extract color name from a user id. The user's id have a short string that indicates the color a user will have
These are the possible colors and codes
pur => purple
ora => orange
bla => black
pnk => pink
users without color
const users = [
{
id: 'u1pur33',
},
{
id: 'u1ora29',
}
]
This is the result i want to achieve
const users = [
{
id: 'u1pur33',
color: 'purple
},
{
id: 'u1ora29',
color: orange
}
]
This is what i have tried so far. i could only add the color to the object but i can't proceed
// create a new array with color
const newUser = users.map(user => ({...user}), color: '')
// colors
const colors = [
{color: 'purple', colorCode: 'pur'},
{color: 'orange', colorCode: 'ora'},
{color: 'black', colorCode: 'bla'},
{color: 'pink', colorCode: 'pnk'}
]

Open up your map with normal braces like this so you can write some code to determine which color to choose.
const colors = {
'pur': 'purple'
....
};
const newUser = users.map(user => {
const code = user.id.substring(2, 5);
return {...user, 'color': colors[code]};
});

Related

Mapping through array of objects after filtering and displaying dynamic common property as a header

I have an array of objects:
const students = [
{ name: 'Tom', class: "Blue" },
{ name: 'Pom', class: "Blue" },
{ name: 'Max', class: "Red" },
{ name: 'Alex', class: "Red" },
{ name: 'John', class: "Yellow" }
];
And I would like to group the return values by the class property, so I can achieve something similar to this in HTML:
Class Blue: Tom, Pom
Class Red: Max, Alex
Class Yellow: John
note: the class property should be displayed once as HTML mark-up which is the reason I don't think this helps at all..
How should I go about it? I can user filter() (like below) but this is rather silly. I would ideally like to avoid doing this several times especially given the class property is dynamic (not known before hand).
const classRed = students.filter(student => student.class === "Red);
const classBlue = students.filter(student => student.class === "Blue);
...
I started this jsfiddle, but not sure how to deal with this object to display how I want it.
I guess this question is about getting the right data structure so I can then map through it to display what I need, rather than simply sorting the array.
Use reduce method to do the group by operation and use Object.entries to get the list of items to iterate.
Try like this
{
Object.entries(
students.reduce((prevValue, currValue) => {
prevValue[currValue.class]
? prevValue[currValue.class].push(currValue.name)
: (prevValue[currValue.class] = [currValue.name]);
return prevValue;
}, {})
).map(([classs, names]) => `Class ${classs}: ${names.join(", ")}`);
}
function App({}) {
const students = [
{ name: "Tom", class: "Blue" },
{ name: "Pom", class: "Blue" },
{ name: "Max", class: "Red" },
{ name: "Alex", class: "Red" },
{ name: "John", class: "Yellow" }
];
return (
<div>
{Object.entries(
students.reduce((prevValue, currValue) => {
prevValue[currValue.class]
? prevValue[currValue.class].push(currValue.name)
: (prevValue[currValue.class] = [currValue.name]);
return prevValue;
}, {})
).map(([classs, names]) => (
<div>{`Class ${classs}: ${names.join(", ")}`}</div>
))}
</div>
);
}
ReactDOM.render(<App />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
JS Fiddle => https://jsfiddle.net/9ahtz2jd/11/
NOTE: Always try to use filter, map, reduce functions.
You could create a new object with the name of the classes as keys and an array with the names of the students as values.
const students = [
{ name: 'Tom', class: "Blue" },
{ name: 'Pom', class: "Blue" },
{ name: 'Max', class: "Red" },
{ name: 'Alex', class: "Red" },
{ name: 'John', class: "Yellow" }
];
let klasses = {};
for (let i = 0; i < students.length; i++) {
let student = students[i];
let klass = student.class;
if (!klasses[klass]) {
klasses[klass] = [student.name];
} else {
klasses[klass].push(student.name);
}
}
console.log(klasses);
let classes = {};
for(let student of students) {
classes[student.class] = [...classes[student.class] || [], student.name];
}
console.log(classes);

How do I update an object's state keeping the existing elements using useState hook?

I have an array of objects:
// seedColors.js
export default [
{
paletteName: "Material UI Colors",
colors: [
{ name: "red", color: "#F44336" },
{ name: "pink", color: "#E91E63" },
]
},
{
paletteName: "Flat UI Colors v1",
colors: [
{ name: "Turquoise", color: "#1abc9c" },
{ name: "Emerald", color: "#2ecc71" },
]
}
]
In my app.js file, I'm creating a new array of object, how would I append the new object to the existing object using useState hook?
// app.js
import seedColors from "./seedColors";
function App() {
const [palettes, setPalettes] = useState({ palettes: seedColors });
const savePalette = (newPalette) => {
// newPalette = { paletteName: "New Test Palette", colors: [{ color: "blue", name: "blue" }] };
setPalettes({ ...palettes, palettes: newPalettes });
};
This isn't updating the original object state, instead it is crashing the application
I would want the state to be updated to:
[
{
paletteName: "Material UI Colors",
colors: [
{ name: "red", color: "#F44336" },
{ name: "pink", color: "#E91E63" },
]
},
{
paletteName: "Flat UI Colors v1",
colors: [
{ name: "Turquoise", color: "#1abc9c" },
{ name: "Emerald", color: "#2ecc71" },
]
},
{
paletteName: "New Test Palette",
colors: [
{ color: "blue", name: "blue" },
]
},
]
Your application is likely "crashing" because you have a typo:
setPalettes({ ...palettes, palettes: newPalettes });
// ^
You don't have a variable with name newPalettes. But even if you fix that, it doesn't produce the result you want.
Is there a reason you are setting the state to be an object with a single property? If not, just assign the array directly (which seems to be what you want based on your description of what you want the state to look like):
const [palettes, setPalettes] = useState(seedColors);
Then you can update the array with
setPalettes([...palettes, newPalette]);
If you need that object, then it would be:
setPalettes({...palettes, palettes: [...palettes.palettes, newPalette]});
You declared const [palettes, setPalettes] = useState({ palettes: seedColors });
but you try to save as setPalettes({ ...palettes, palettes: newPalettes });
I would suggest to save them as on object:
const [palettes, setPalettes] = useState(seedColors);
setPalettes({ ...palettes, newPalettes });`

office-ui-fabric / fluent-ui Grouped DetailsList

Today I tried to use the Grouped DetailsList of the fluent-ui.
What I expected: I need to declare some groups, let's say red, blue, green and then just add to each item, I want to add to the List, a specific property, that maps the Item to the groups.
e.g.:
groups: [
{ key: 'red', name: 'Color: "red"'},
{ key: 'green', name: 'Color: "green"'},
{ key: 'blue', name: 'Color: "blue"' },
],
items: [...,
{ key: 'red',anyProp1: "abc", anyProp2: "dfg",...},
...,
]
What I found out I have to do: I need to sort the Array, which contains my items in that way, that all Items belonging to the Group red need to be in one block. e.g.: [red, red, red, blue, blue, green, green, green]. Now I needed to provide the information about startIndex and count to map my Array of items to the groups.
This is what a definition of a group could look like:
groups: [
{ key: 'groupred0', name: 'Color: "red"', startIndex: 0, count: 2, level: 0 },
{ key: 'groupgreen2', name: 'Color: "green"', startIndex: 2, count: 0, level: 0 },
{ key: 'groupblue2', name: 'Color: "blue"', startIndex: 2, count: 3, level: 0 },
],
I can't understand why they have done it this way (For me it's very inconvenient this way). So, while I'm more between a beginner and an intermediate in JS. I think the guys who implemented this are professionals. There must be a reason. Maybe it has something todo with performance? I could imagine that when it comes to very large lists, it performs better this way, but I'm not sure.
Does anybody knows some details about this and can explain?
Faced the same issue and got a clue here. Then bult my solution.
Following is the function to generate groups array from the given items list sorted by the grouping column:
function groupsGenerator(itemsList, fieldName) {
// Array of group objects
const groupObjArr =[]
// Get the group names from the items list
const groupNames = [...new Set(itemsList.map(item => item[fieldName]))]
// Iterate through each group name to build proper group object
groupNames.forEach(gn => {
// Count group items
const groupLength = itemsList.filter(item => item[fieldName] === gn).length
// Find the first group index
const groupIndex = itemsList.map(item => item[fieldName]).indexOf(gn)
// Generate a group object
groupObjArr.push({
key: gn, name: gn, level: 0, count: groupLength, startIndex: groupIndex
})
})
// The final groups array returned
return groupObjArr
}
Typed and with empty group name option variant of the Timus's answer
function generateGroups(items: any[], fieldName: string, emptyGroupName: string = '-'): IGroup[] {
const groups: IGroup[] = []
const groupNames = [...new Set<string>(items.map(item => item[fieldName]))]
groupNames.forEach(name => {
const groupItemsCount = items.filter(item => item[fieldName] === name).length
const groupStartIndex = items.map(item => item[fieldName]).indexOf(name)
groups.push({
key: name,
level: 0,
name: name ?? emptyGroupName,
count: groupItemsCount,
startIndex: groupStartIndex
})
})
return groups
}

Why JavaScript deconstructing not working inline

In hash color function, I assign title and rating by deconstructing them from another object but instead it assign the full color object, and if I break the code into two lines (first deconstructing and assign(reconstructing) then it works fine. Please explain the logic running behind this.
const colors = [{
id: '-xekare',
title: "rad red",
rating: 3
}, {
id: '-jbwsof',
title: "big blue",
rating: 2
}, {
id: '-prigbj',
title: "grizzly grey",
rating: 5
}, {
id: '-ryhbhsl',
title: "banana",
rating: 1
}]
hashcolor=colors.reduce((hash,color)=>{
hash[color.id]={title,rating}=color
return hash
},[])
console.log(hashcolor);
When you're destructuring, you're creating (or assigning to) individual variables - you're not creating a new object, so hash[color.id] = { title, rating } doesn't actually work. You could write (or copy) a pick function that accomplishes that, but in this case, you could just destructure in the arguments instead.
You should also probably use an object as the accumulator, rather than an array:
const colors = [{
id: '-xekare',
title: "rad red",
rating: 3
}, {
id: '-jbwsof',
title: "big blue",
rating: 2
}, {
id: '-prigbj',
title: "grizzly grey",
rating: 5
}, {
id: '-ryhbhsl',
title: "banana",
rating: 1
}]
const hashcolor = colors.reduce((hash, { id, title, rating }) => {
hash[id] = { title, rating };
return hash;
}, {})
console.log(hashcolor);
Although it looks the same, there are actually 2 phases to a creation of an object from destructured properties:
Destructure and assign the properties to variables (or consts) - const { title, rating } = color.
Use shorthand property names to create the object const obj = { title, rating }.
In your case you can move the destructuring phase to the function call:
const colors = [{"id":"-xekare","title":"rad red","rating":3},{"id":"-jbwsof","title":"big blue","rating":2},{"id":"-prigbj","title":"grizzly grey","rating":5},{"id":"-ryhbhsl","title":"banana","rating":1}]
const hashcolor = colors.reduce((hash, { id, title, rating }) => {
hash[id] = { title, rating }
return hash
}, {})
console.log(hashcolor);
And you can also use object rest, to create the object:
const colors = [{"id":"-xekare","title":"rad red","rating":3},{"id":"-jbwsof","title":"big blue","rating":2},{"id":"-prigbj","title":"grizzly grey","rating":5},{"id":"-ryhbhsl","title":"banana","rating":1}]
const hashcolor = colors.reduce((hash, { id, ...newColor }) => {
hash[id] = newColor
return hash
}, {})
console.log(hashcolor);

javascript merge arrays into a single object

I am trying to merge several arrays into a single object that I can then iterate to use in chart.js datasets. I have a set of data that looks like this:
export const data = [
{
'name': 'Flow',
'values': {
'sent': 410,
'responded': 253,
'secured': 65
}
}
]
(I limited this to just one, but the dataset is much larger)
Then I have several arrays that I've built based on this data:
this.labels = data.map(item => item.name);
this.colors = ['#439ff4', '#5ec3d5', '#a068e5'];
this.responded = data.map(item => item.values.responded);
this.sent = data.map(item => item.values.sent);
this.secured = data.map(item => item.values.secured);
What I need to do is this:
get the key names (responded, sent, secured) as another array
merge the keys, colors, responded, sent, and secured, arrays into an object called datasets.
this.datasets = [ /* not sure what to do here! */];
Ultimately my chart in chart js is looking for something like this (I have partially hard-coded values at the moment:
datasets: [
{
label: 'Sent',
data: this.sent,
backgroundColor: '#439ff4'
},
{
label: 'Responded',
data: this.responded,
backgroundColor: '#5ec3d5'
},
{
label: 'Secured',
data: this.secured,
backgroundColor: '#a068e5'
}
],
that I would ultimately like to just express as
datasets: this.datasets,
I hope I explained this well enough as to what I am trying to do.
Assuming that the key names in data.values stays in lowercase and otherwise it is same as datasets[*].label, you can do something like below.
// the custom type is just for making it more manageable, omit it if you want
type DatasetItem = { label: string, data: number[], backgroundColor: string };
let datasets: Array<Partial<DatasetItem>> = [
{
label: 'Sent',
backgroundColor: '#439ff4'
},
{
label: 'Responded',
backgroundColor: '#5ec3d5'
},
{
label: 'Secured',
backgroundColor: '#a068e5'
}
];
const data = [
{
'name': 'Flow1',
'values': {
'sent': 410,
'responded': 253,
'secured': 65
}
},
{
'name': 'Flow2',
'values': {
'sent': 411,
'responded': 254,
'secured': 66
}
}
];
datasets.forEach((item) => item.data = data.map((d) => d.values[item.label.toLowerCase()]));
console.log(datasets);

Categories

Resources