New Map from JSON data with unique values - javascript

I'm trying to create a new map of [key:value] as [trait_type]:[{values}]
So taking the below data it should look like:
[Hair -> {"Brown", "White-Blue"},
Eyes -> {"Green", "Red"}
]
Heres my json obj
[
{
"name":"Charlie",
"lastname":"Gareth",
"date":1645462396133,
"attributes":[
{
"trait_type":"Hair",
"value":"Brown"
},
{
"trait_type":"Eyes",
"value":"Red"
}
]
},
{
"name":"Bob",
"lastname":"James",
"date":1645462396131,
"attributes":[
{
"trait_type":"Hair",
"value":"White-Blue"
},
{
"trait_type":"Eyes",
"value":"green"
}
]
}
];
To note: I'm also trying to make it the values unique so If I have 2 people with red eyes the value would only ever appear once.
This is what I have so far, kind of works but in the console window the values come out as a char array.
let newData = data.map((item) =>
item.attributes.map((ats) => {
return { [ats.trait_type]: [...ats.value] };
})
);
newData.map((newItem) => console.log(newItem));

You could take an object and iterate the nested data with a check for seen values.
const
data = [{ name: "Charlie", lastname: "Gareth", date: 1645462396133, attributes: [{ trait_type: "Hair", value: "Brown" }, { trait_type: "Eyes", value: "Red" }] }, { name: "Bob", lastname: "James", date: 1645462396131, attributes: [{ trait_type: "Hair", value: "White-Blue" }, { trait_type: "Eyes", value: "green" }] }],
result = data.reduce((r, { attributes }) => {
attributes.forEach(({ trait_type, value }) => {
r[trait_type] ??= [];
if (!r[trait_type].includes(value)) r[trait_type].push(value);
})
return r;
}, {});
console.log(result);

try this
const extractTrait = data =>
data.flatMap(d => d.attributes)
.reduce((res, {
trait_type,
value
}) => {
return {
...res,
[trait_type]: [...new Set([...(res[trait_type] || []), value])]
}
}, {})
const data = [{
"name": "Charlie",
"lastname": "Gareth",
"date": 1645462396133,
"attributes": [{
"trait_type": "Hair",
"value": "Brown"
},
{
"trait_type": "Eyes",
"value": "Red"
}
]
},
{
"name": "Bob",
"lastname": "James",
"date": 1645462396131,
"attributes": [{
"trait_type": "Hair",
"value": "White-Blue"
},
{
"trait_type": "Eyes",
"value": "green"
}
]
}
];
console.log(extractTrait(data))

Related

JavaScript - filter in loop, create duplicate

I want to filter an array with another array in order to know if there are new people.
const people = [
{ "name": "jerry" },
{ "name": "tom" },
{ "name": "alex" }
]
const newList = [
{ "name": "bran" },
{ "name": "jerry" },
{ "name": "john" }
]
const new_people = []
for (const pp of people) {
let result = newList.filter(newL => newL.name != pp.name)
if (result) {
new_people.push(result)
}
}
console.log(new_people)
This is the result:
[
[ { name: 'bran' }, { name: 'john' } ],
[ { name: 'bran' }, { name: 'jerry' }, { name: 'john' } ],
[ { name: 'bran' }, { name: 'jerry' }, { name: 'john' } ]
]
But I'm looking for:
[ { name: 'bran' }, { name: 'john' } ]
I would like to avoid the loop because it makes duplicate in the result but I don't know how I can't do it without the loop.
First make a temporary array of people name:
const peopleNames = people.map(pp => pp.name);
Then the peopleNames will be as follows:
['jerry', 'tom', 'alex']
Now filter the new people from the newList:
const newPeople = newList.filter(pp => !peopleNames.includes(pp.name));
The newPeople will be an array of objects that you are looking for.
[{name: 'bran'}, {name: 'john'}]
const people = [
{ "name": "jerry" },
{ "name": "tom" },
{ "name": "alex" }
]
const newList = [
{ "name": "bran" },
{ "name": "jerry" },
{ "name": "john" }
]
const output = newList.filter(a => people.filter(x => x.name == a.name).length == 0);
console.log('By USing Filter', output);
//filter the newList and retain those object, which are not present in the people
//Way 2: By using some
//const output2 = newList.filter(a => !people.some(x => x.name == a.name));
//console.log('By Using Some', output2);
You can use Array's reduce method to get the desired result:
const new_people = newList.reduce((accVal, e) =>
(people.map(p => p.name).includes(e.name))
? accVal
: accVal.concat({ "name": e.name } ),
[ ] )

ReactJS Convert json to [name: value:] pair

I have this json object.
[
{
"crime": "LARCENY-NON_VEHICLE",
"count": "23217"
},
{
"crime": "AUTO_THEFT",
"count": "13675"
},
{
"crime": "LARCENY-FROM_VEHICLE",
"count": "28627"
},
{
"crime": "BURGLARY-RESIDENCE",
"count": "16312"
}
]
I need to display this data in a pie chart so I need to convert it to this format.
[
{name: "LARCENY-NON_VEHICLE", value: 23217},
{name: "AUTO_THEFT", value: 13675},
{name: "LARCENY-FROM_VEHICLE", value: 28627},
{name: "BURGLARY-RESIDENCE", value: 16312}
]
This is how Im retrieving the data using axios.
You can just use map to return a new array with values from old array
const data = [{
"crime": "LARCENY-NON_VEHICLE",
"count": "23217"
},
{
"crime": "AUTO_THEFT",
"count": "13675"
},
{
"crime": "LARCENY-FROM_VEHICLE",
"count": "28627"
},
{
"crime": "BURGLARY-RESIDENCE",
"count": "16312"
}
];
const newData = data.map(item => {
return {
name: item.crime,
value: +item.count // + to convert string to number
}
});
console.log(newData)
You can simply format an array by calling map function
const arr = [
{
crime: "LARCENY-NON_VEHICLE",
count: "23217",
},
{
crime: "AUTO_THEFT",
count: "13675",
},
{
crime: "LARCENY-FROM_VEHICLE",
count: "28627",
},
{
crime: "BURGLARY-RESIDENCE",
count: "16312",
},
];
arr.map((e) => ({
name: e.crime,
count: Number.parseInt(e.count)
}))

Manipulate Object to group based on Array Object List

I'm trying to find a way to convert this list of objects based on the group array. The tricky part I've found is iterating through the group Array and applying the object to more than one place if there are multiple groups.
I'm also trying to ignore any group that does not belong to anything. I've tried using the reduce function but I cannot get the iteration through the group array.
let cars =
[
{
"group":[],
"name": "All Makes",
"code": ""
},
{
"group":["Group A"],
"name": "BMW",
"code": "X821"
},
{
"group":["Group B"],
"name": "Audi",
"code": "B216"
},
{
"group":["Group B"],
"name": "Ford",
"code": "P385"
},
{
"group":["Group B", "Group C"],
"name": "Mercedes",
"code": "H801"
},
{
"group":["Group C"],
"name": "Honda",
"code": "C213"
}
]
To become this:
[
{
"group": "Group A",
"cars": [
{
name: "BMW",
code: "X821"
}
]
},
{
"group": "Group B",
"cars": [
{
name: "Audi",
code: "B216"
},
{
name: "Ford",
code: "P385"
},
{
name: "Mercedes",
code: "H801"
}
]
},
{
"group": "Group C",
"cars": [
{
name: "Mercedes",
code: "H801"
},
{
name: "Honda",
code: "C213"
}
]
}
]
I've already tried using reduce to accomplish this but it doesn't quite get the desired affect.
const res = cars.reduce((acc, {group, ...r}) => {
group.forEach(key => {
acc[key] = (acc[key] || []).concat({...r});
});
return acc;
}, []);
console.log(res);
Using string keys on arrays doesn't work quite well, that's what objects are for, then use Object.values to get the array out of it. Also you want to put objects and not arrays in there:
const res = Object.values(cars.reduce((acc, {group, ...r}) => {
group.forEach(key => {
(acc[key] = (acc[key] || { group, cars: [] })).cars.push(r);
});
return acc;
}, {}));
I'd write it this way:
const byGroup = new Map();
for(const { group, ...rest } of cars) {
if(!byGroup.has(group))
byGroup.set(group, { group, cars: [] });
byGroup.get(group).cars.push(rest);
}
const result = [...byGroup.values()];
You need to take an object as accumulator and then map the entries fro getting the wanted result.
let cars = [{ group: [], name: "All Makes", code: "" }, { group: ["Group A"], name: "BMW", code: "X821" }, { group: ["Group B"], name: "Audi", code: "B216" }, { group: ["Group B"], name: "Ford", code: "P385" }, { group: ["Group B", "Group C"], name: "Mercedes", code: "H801" }, { group: ["Group C"], name: "Honda", code: "C213" }],
result = Object
.entries(cars.reduce((acc, { group, ...r }) => {
group.forEach(key => acc[key] = (acc[key] || []).concat({...r}));
return acc;
}, {}))
.map(([group, cars]) => ({ group, cars }));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to group from array object

I using code form "
I am looking for best ways of doing this. I have group:
data
[
{
"date": "16/04/2020",
"count": 0,
"name": "A"
},
{
"date": "16/04/2020",
"count": 1,
"name": "B"
},
{
"date": "17/04/2020",
"count": 0,
"name": "B"
}
//...More.....
]
Answer
{
"date": "04/2020",
"symtom": {
"data": [
{
"date": "16/04/2020",
"data": [
{
"name": "A",
"count": [
{
"date": "16/04/2020",
"count": 0,
"name": "A"
}
]
},
{
"name": "B",
"count": [
{
"date": "16/04/2020",
"count": 1,
"name": "B"
}
]
},
//...More.....
]
},
{
"date": "17/04/2020",
"data": [
{
"name": "B",
"count": [
{
"date": "17/04/2020",
"count": 0,
"name": "B"
}
]
},
//...More.....
]
}
]
}
}
Can I fix the code and to get the desired answer?
Code :
const items = [
{
tab: 'Results',
section: '2017',
title: 'Full year Results',
description: 'Something here',
},
{
tab: 'Results',
section: '2017',
title: 'Half year Results',
description: 'Something here',
},
{
tab: 'Reports',
section: 'Marketing',
title: 'First Report',
description: 'Something here',
}
];
function groupAndMap(items, itemKey, childKey, predic){
return _.map(_.groupBy(items,itemKey), (obj,key) => ({
[itemKey]: key,
[childKey]: (predic && predic(obj)) || obj
}));
}
var result = groupAndMap(items,"tab","sections",
arr => groupAndMap(arr,"section", "items"));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
ref : Group array of object nesting some of the keys with specific names
But I would like to have the answer line this (Answer) :
{
"date": "04/2020",
"symtom": {
"data": [
{
"date": "16/04/2020",
"data": [
{
"name": "A",
"count": 0,
},
{
"name": "B",
"count": 1,
},
//...More.....
]
},
{
"date": "17/04/2020",
"data": [
{
"name": "B",
"count":0,
},
//...More.....
]
}
]
}
}
Thanks!
I am a beginner but it looks like you want system.data.data to = an array of objects with the keys name:str and count:number but instead you are applying the whole object into count so the key count:{name:A, count:0,date:etc}.
I really can't follow your function which separates the data... but all you should have to do is when count is sent the object to reference just do a dot notation like object.count to access the number vs the object that way you will have the desired affect. Hopefully that is what you were asking.
I would use a helper function groupBy (this version is modeled after the API from Ramda [disclaimer: I'm one of its authors], but it's short enough to just include here.) This takes a function that maps an object by to a key value, and then groups your elements into an object with those keys pointing to arrays of your original element.
We need to use that twice, once to group by month and then inside the results to group by day. The rest of the transform function is just to format your output the way I think you want.
const groupBy = (fn) => (xs) =>
xs .reduce((a, x) => ({... a, [fn(x)]: [... (a [fn (x)] || []), x]}), {})
const transform = (data) =>
Object .entries (groupBy (({date}) => date.slice(3)) (data)) // group by month
.map (([date, data]) => ({
date,
symtom: {
data: Object .entries (groupBy (({date}) => date) (data)) // group by day
.map (([date, data]) => ({
date,
data: data .map (({date, ...rest}) => ({...rest})) // remove date property
}))
}
}))
const data = [{date: "16/04/2020", count: 0, name: "A"}, {date: "16/04/2020", count: 1, name: "B"}, {date: "17/04/2020", count: 0, name: "B"}, {date: "03/05/2020", count: 0, name: "C"}];
console .log (
transform (data)
)
.as-console-wrapper {min-height: 100% !important; top: 0}
If you need to run in an environment without Object.entries, it's easy enough to shim.
You could take a function for each nested group and reduce the array and the grouping levels.
var data = [{ date: "16/04/2020", count: 0, name: "A" }, { date: "16/04/2020", count: 1, name: "B" }, { date: "17/04/2020", count: 0, name: "B" }],
groups = [
(o, p) => {
var date = o.date.slice(3),
temp = p.find(q => q.date === date);
if (!temp) p.push(temp = { date, symptom: { data: [] } });
return temp.symptom.data;
},
({ date }, p) => {
var temp = p.find(q => q.date === date);
if (!temp) p.push(temp = { date, data: [] });
return temp.data;
},
({ date, ...o }, p) => p.push(o)
],
result = data.reduce((r, o) => {
groups.reduce((p, fn) => fn(o, p), r);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Javascript Object Tranformation

I am using the map to transforming the JSON. Instead of Single object, I am getting an Array of data.
Snipt Shown Below.
I am trying to achieve following JSON
{
"data": {
"test1": {
"abc": {
"size": "big",
"id": "1"
}
},
"test2": {
"abc": {
"size": "small",
"id": "2"
}
}
}
}
But getting following JSON
{
"data": [{
"test1": {
"abc": {
"size": "big",
"id": "1"
}
}
}, {
"test2": {
"abc": {
"size": "big",
"id": "2"
}
}
}]
}
Here is my code.
const test = [{ id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9',
ad_id: 'test1',
country: 'ID',
abc: { size: 'big', id: '1' },
},
{ id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9',
ad_id: 'test2',
country: 'ID',
abc: { size: 'small', id: '2' },
},
];
const transformedTest = test.map(result =>
({ [result.ad_id]: { abc: result.abc } }));
const data = { data: transformedTest };
console.log(JSON.stringify(data));
Any help will be appreciated
Try this:
const test = [
{
"id": "ddec9c7f-95aa-4d07-a45a-dcdea96309a9",
"ad_id": "test1",
"country": "ID",
"abc": {
"size": "big",
"id": "1"
}
},
{
"id": "ddec9c7f-95aa-4d07-a45a-dcdea96309a9",
"ad_id": "test2",
"country": "ID",
"abc": {
"size": "big",
"id": "2"
}
}
];
const result = test.reduce((acc,{ad_id, abc})=> (acc.data[ad_id] = {abc}, acc),{data:{}})
console.log(result);
const transformedTest = test.reduce((pv, result) =>
({...pv, [result.ad_id]: { abc: result.abc } }), {});
You could take Object.fromEntries and map new key/value pairs and get a new object from it.
const
test = [{ id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9', ad_id: 'test1', country: 'ID', abc: { size: 'big', id: '1' } }, { id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9', ad_id: 'test2', country: 'ID', abc: { size: 'small', id: '2' } }];
transformedTest = Object.fromEntries(test.map(({ ad_id, abc} ) => [ad_id, { abc }]));
data = { data: transformedTest };
console.log(data);
Loop through the array using a simple for...of loop and create a data object. Use Shorthand property names to create the abc nesting:
const test=[{id:'ddec9c7f-95aa-4d07-a45a-dcdea96309a9',ad_id:'test1',country:'ID',abc:{size:'big',id:'1'},},{id:'ddec9c7f-95aa-4d07-a45a-dcdea96309a9',ad_id:'test2',country:'ID',abc:{size:'small',id:'2'}}]
const data = {}
for(const { ad_id, abc } of test) {
data[ad_id] = { abc }
}
console.log({ data })
.as-console-wrapper { min-height: 100%; }
The function map returns an array rather than a specific key-value object, an alternative is using the function reduce to build the desired output.
const test = [{ id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9', ad_id: 'test1', country: 'ID', abc: { size: 'big', id: '1' },},{ id: 'ddec9c7f-95aa-4d07-a45a-dcdea96309a9', ad_id: 'test2', country: 'ID', abc: { size: 'big', id: '2' },}],
data = { data: test.reduce((a, result) =>
({...a, [result.ad_id]: { abc: result.abc } }), Object.create(null))};
console.log(JSON.stringify(data, null, 2));
.as-console-wrapper { min-height: 100%; }

Categories

Resources