How to reformat object using its property value as property key? - javascript

how can I assign object property value as property key?
I have a set of data:
const mydata = [
{
"id": 001,
"value": "Value 1",
"title": "Title 1"
},
{
"id": 002,
"value": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
],
"title": "Title 2"
},
]
I want to reformat it to become:
const mydata = [
{
"Title 1": "Value 1"
},
{
"Title 2": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
]
},
]
I have tried this code to achieve it:
mydata.map((dt: any) => {
dt.title: dt.value
});
However, it seems not working.
Any idea how can I reformat it to the one I desire?
Thanks.

Please use following code.
Reference URL How to use a variable for a key in a JavaScript object literal?
const mydata = [
{
"id": 001,
"value": "Value 1",
"title": "Title 1"
},
{
"id": 002,
"value": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
],
"title": "Title 2"
},
];
let reData = [];
mydata.forEach((dt)=>{
reData.push({[dt.title]: dt.value});
});
console.log(reData);

If you want to transform the array to a different type of variable, use [reduce][1]
const mydata = [
{
id: 001,
value: "Value 1",
title: "Title 1",
},
{
id: 002,
value: [
{
Name: "Name 1",
Age: "20",
},
{
Name: "Name 2",
Age: "30",
},
],
title: "Title 2",
},
];
const data = mydata.reduce(
(acc, cur) => ({ ...acc, [cur.title]: cur.value }),
{}
);
console.log(data);

Your map function has an error, and your key assignment has another one. Let's fix it.
const newData = mydata.map((dt: any) => ({
[dt.title]: dt.value,
}));
First: You can't return an object from an arrow function without parenthesis, if you don't use it, the code will think it is a function body not an object.
Second: If you want to return a value as a key, you need put it inside "[ ]" (Square brackets)
Just that, simple mistakes, at the end you came up with the right logic to solve it

Add brackets around the return value.
Use square brackets for a computed property name.
const mydata = [
{
"id": 001,
"value": "Value 1",
"title": "Title 1"
},
{
"id": 002,
"value": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
],
"title": "Title 2"
},
];
const res = mydata.map(({value, title})=>({[title]: value}));
console.log(res);

Related

How to convert array of object into nested array of object in Javascript?

I am having an array of objects like this
[
{
name: "dhanush",
goals: ["goal 1","goal 2"],
goalAmount: ["10000","20000"]
},
{
name: "kumar",
goals: ["goal 3", "goal 4"],
goalAmount: ["30000","40000"]
},
{
name: "test",
goals: ["goal 5"],
goalAmount: ["50000"],
}
]
Is that possible to convert the above array of object into the below structure like this
[
{
"name": "dhanush",
"goals": "---",
"goalAmount":"---",
"subRows": [
{
"name": "",
"goals": "goal 1",
"goalAmount":" 10000"
},
{
"name": "",
"goals": "goal 2",
"goalAmount":" 20000"
}
]
},
{
"name": "kumar",
"goals": "---",
"goalAmount":"---",
"subRows": [
{
"name": "",
"goals": "goal 3",
"goalAmount":" 30000"
},
{
"name": "",
"goals": "goal 4",
"goalAmount":" 40000"
}
]
},
{
"name": "Test",
"goals": "goal 5",
"goalAmount":"50000"
}
]
In the first data, you can see the user has multiple goals (which means the array length is more than 1), If the goal length is more than one, need to create another key and move the goal data into the above structure like this.
Why I am doing this because I got an ask to create a table that needs to support expandable rows. I used #tanstack/react-table for this row expansion. Here you can find the working demo link - https://codesandbox.io/s/tanstack-table-expansion-1t77ks?file=/src/App.js
In the demo, you can see the row can expand. For the expansion that table requires the data format like this.
I tried to do something like this,
var data = [
{
name: "dhanush",
goals: ["goal 1","goal 2"]
},
{
name: "kumar",
goals: ["goal 3", "goal 4"]
},
{
name: "test",
goals: ["goal 5"]
}
]
let result = data.map((val,i) => {
return {
name: val.name,
...(val.goals.length === 1 && {goals: val.goals[0]}),
[val.goals.length > 1 && 'subRows']: data.map((t,j) => {
return{
name: "",
goals: val.goals[j]
}
}),
}
})
But the output I am getting like this instead of the actual structure
[
{
"name": "dhanush",
"subRows": [
{
"name": "",
"goals": "goal 1"
},
{
"name": "",
"goals": "goal 2"
},
{
"name": ""
}
]
},
{
"name": "kumar",
"subRows": [
{
"name": "",
"goals": "goal 3"
},
{
"name": "",
"goals": "goal 4"
},
{
"name": ""
}
]
},
{
"name": "test",
"goals": "goal 5",
"false": [
{
"name": "",
"goals": "goal 5"
},
{
"name": ""
},
{
"name": ""
}
]
}
]
Could you please help to achieve this?
This here
[val.goals.length > 1 && 'subRows']: data.map((tm j) => {
evaluates to false if there's 1 goal or less, and results in the string property false. Then you're mapping the whole data again inside that for some reason. Only map over the goals of the current element you're iterating over, the val.goals.
Because the different possible resulting objects are pretty differently strucured, I think this would be easier to manage if they were entirely separate - return { name, goals: goals[0] } if there's only one goal, and return a completely different object mapping over the goals otherwise.
var data=[{name:"dhanush",goals:["goal 1","goal 2"],goalAmount:["10000","20000"]},{name:"kumar",goals:["goal 3","goal 4"],goalAmount:["30000","40000"]},{name:"test",goals:["goal 5"],goalAmount:["50000"]}];
const result = data.map(({ name, goals, goalAmount }) => {
return goals.length === 1
? { name, goals: goals[0], goalAmount: goalAmount[0] }
: {
name,
goals: '---',
subRows: goals.map(
(goal, i) => ({ name: '', goal, goalAmount: goalAmount[i] })
)
};
});
console.log(result);
Don't try to do this all in a single object literal, it's a confusing way to create properties conditionally. Just write normal conditional statements.
To get the goalAmount, use the index argument to the map() callback function so you can get the corresponding element in another array.
var data = [
{
name: "dhanush",
goals: ["goal 1","goal 2"],
goalAmount: ["10000","20000"]
},
{
name: "kumar",
goals: ["goal 3", "goal 4"],
goalAmount: ["30000","40000"]
},
{
name: "test",
goals: ["goal 5"],
goalAmount: ["50000"],
}
]
var result = data.map(({
name,
goals,
goalAmount
}) => {
let item = {
name
};
if (goals.length == 1) {
item.goals = goals[0];
item.goalAmount = goalAmount[0];
} else {
item.goals = "---";
item.subRows = goals.map((g, i) => ({
name: "",
goals: g,
goalAmount: goalAmount[i]
}));
}
return item;
});
console.log(result);

React Native - sort array based off values in common

Hey guys I have the following array that's used to display a flatlist within my app.
Array [
Object {
"data": "Item 1",
"id": "1",
"subjects": "1,8,9,23,11,15,16,14,20",
},
Object {
"data": "Item 2",
"id": "2",
"subjects": "8,11,2,4,16,19",
},
Object {
"data": "Item 3",
"id": "3",
"subjects": "16,20,14,11,9,2",
},
Object {
"data": "Item 4",
"id": "4",
"subjects": "1,16,19",
},
]
However I would like to sort this array based off the subjects value. In the app the user can select a couple of subjects which are represented by numbers so lets say the users selected subjects are:
11, 4, 2, 1
I would like to sort the array so that the items with 3 or more subjects in common with the user are sorted to the top and then items with two and then 1 and then none so the array above should look like this after sorting:
Array [
Object {
"data": "Item 2",
"id": "2",
"subjects": "8,11,2,4,16,19",
},
Object {
"data": "Item 1",
"id": "1",
"subjects": "1,8,9,23,11,15,16,14,20",
},
Object {
"data": "Item 3",
"id": "3",
"subjects": "16,20,14,11,9,2",
},
Object {
"data": "Item 4",
"id": "4",
"subjects": "0,16,19",
},
]
How can I achieve this?
I have been searching around the array sort function:
Array.prototype.sort()
However I have only seen how to sort based off number comparisons I have never seen an array sorted based off values in common. Please could someone help me with this!
EDIT
Array [
Object {
"data": "Item 2",
"id": "2",
"subjects": "8,11,2,4,16,19",
"ranking": "green",
},
Object {
"data": "Item 1",
"id": "1",
"subjects": "1,8,9,23,11,15,16,14,20",
"ranking": "amber",
},
Object {
"data": "Item 3",
"id": "3",
"subjects": "16,20,14,11,9,2",
"ranking": "amber",
},
Object {
"data": "Item 4",
"id": "4",
"subjects": "0,16,19",
"ranking": "red",
},
]
You could create an object with counts of selected subjects and sort descending by this value.
const
data = [{ data: "Item 1", id: "1", subjects: "1,8,9,23,11,15,16,14,20" }, { data: "Item 2", id: "2", subjects: "8,11,2,4,16,19" }, { data: "Item 3", id: "3", subjects: "16,20,14,11,9,2" }, { data: "Item 4", id: "4", subjects: "1,16,19" }],
selected = [11, 4, 2, 1],
counts = data.reduce((r, { id, subjects }) => {
r[id] = subjects
.split(',')
.reduce((s, v) => s + selected.includes(+v), 0);
return r;
}, {});
data.sort((a, b) => counts[b.id] - counts[a.id]);
console.log(data);
console.log(counts);
.as-console-wrapper { max-height: 100% !important; top: 0; }

lodash filter in array

in lodash there is a possibility to filter within an array which is in an object?
I have an object that has an array in it. It looks like this
{
"id": "1",
"name": "Test 1",
"tag": ["blue","red", "yellow"]
},
{
"id": "2",
"name": "Test 2",
"tag": ["red", "yellow"]
},
{
"id": "3",
"name": "Test 3",
"tag": ["green"]
}
What I want to do now.
If the tag is Red he should output the object with the ids: 1 and 2. Tag = Green only the object with the id: 3. And so on.
I have now tried to solve this with the lodash filter.
const filteredColors = _.filter(colors, function(c) {
return _.includes(['Test 1', 'Test 2'], c.name);
});
// returns Objects with 2 Entrys = Correct
I can filter normal values, but how can I find the value in the array?
I have solved it with:
let filter = _.filter(
colors,
_.flow(
_.property('tag'),
_.partial(_.intersection, ['red', 'green']),
_.size,
),
);
There's no need for lodash, just check if the tag array includes what you're looking for:
const arr = [{
"id": "1",
"name": "Test 1",
"tag": ["blue","red", "yellow"]
},
{
"id": "2",
"name": "Test 2",
"tag": ["red", "yellow"]
},
{
"id": "3",
"name": "Test 3",
"tag": ["green"]
}];
console.log(
arr.filter(({ tag }) => tag.includes('red'))
);
Convert your array to String, and then you can check string is contain your colour or not. Like.
const items = [
{
"id": "1",
"name": "Test 1",
"tag": ["blue","red", "yellow"]
},
{
"id": "2",
"name": "Test 2",
"tag": ["red", "yellow"]
},
{
"id": "3",
"name": "Test 3",
"tag": ["green"]
}]
function findColorId(color){
return items.filter((d)=> {
if(String(d.tag).includes(color)){
return d;
}
});
}
findColorId('red');
You can use Array.prototype.filter():
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
and Array.prototype.map():
The map() method creates a new array with the results of calling a provided function on every element in the calling array.
const colors = [{
"id": "1",
"name": "Test 1",
"tag": ["blue","red", "yellow"]
},
{
"id": "2",
"name": "Test 2",
"tag": ["red", "yellow"]
},
{
"id": "3",
"name": "Test 3",
"tag": ["green"]
}]
function filteredColors(colorsArr, c){
return colorsArr.filter(i => i.tag.includes(c)).map(i => ({id: i.id}));
}
console.log(filteredColors(colors, 'red'));
console.log(filteredColors(colors, 'green'));
This in lodash is somewhat longer than with ES6.
const data = [{ "id": "1", "name": "Test 1", "tag": ["blue","red", "yellow"] }, { "id": "2", "name": "Test 2", "tag": ["red", "yellow"] }, { "id": "3", "name": "Test 3", "tag": ["green"] }]
// lodash
const lodash = c => _.filter(data, x => _.includes(x.tag,c))
// ES6
const es6 = c => data.filter(x => x.tag.includes(c))
console.log(lodash('green'))
console.log(es6('green'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
The idea in both is to simply use _.filter / Array.filter and then _.includes / Array.includes

Ramda to loop over array

Loop may be the wrong term, but it kind of describes what I am attempting.
I want to give structure to flat data, but I also need to keep track of the array it came from.
Basically my rules are (per array):
If level 1 exists- give it the name of the item, and a typechild array. EACH time a level 1 appears (even in the same array) it should create a new entry.
Inside typechild, put the any items with level >1
If NO level 1 exists- give it the name of the item, and a typechild array.
My code below is almost there, with the exception that it should create an array EVERYTIME it sees a level 1. My example will make sense:
Input data
[
{
"title": "Test 1",
"type": [{
"name": "Animal",
"level": 1
},
{
"name": "Food",
"level": 1
},
{
"name": "Chicken",
"level": 3
}
]
},
{
"title": "Test 2",
"type": [{
"name": "Foo",
"level": 2
}]
}
]
Note: Animal and Food are both LEVEL 1 items. So it should create two ARRAYS like so...
Desired output
[
{
name: "Animal",
typechild: [
{
level: 2,
name: "Chicken"
}
]
},
{
name: "Food",
typechild: [
{
level: 2,
name: "Chicken"
}
]
},
{
name: "NoName",
typechild: [
{
level: 2,
name: "Foo"
}
]
}
]
Ramda attempt (try here: https://dpaste.de/JQHw):
const levelEq = (n) => pipe(prop('level'), equals(n));
const topLevel = pipe(prop('type'), find(levelEq(1)));
const topLevelName = pipe(topLevel, propOr('NoName', 'name'));
const extract2ndLevel = pipe(pluck('type'), flatten, filter(levelEq(2)));
const convert = pipe(
groupBy(topLevelName),
map(extract2ndLevel),
map(uniq),
toPairs,
map(zipObj(['name', 'typechild']))
);
Something like this?
var output = [{
"name": "Animal",
"typechild": [{
"name": "Chicken",
"level": 3
}, {
"name": "Dog",
"level": 2
}]
}, {
"name": "Food",
"typechild": [{
"name": "Chicken",
"level": 3
}]
}, {
"name": "No name",
"typechild": [{
"name": "Foo",
"level": 2
}, {
"name": "Baz",
"level": 2
}]
}]
let out = {},
typechild = {},
k;
const data = [{
"title": "Test 1",
"type": [{
"name": "Animal",
"level": 1
}, {
"name": "Food",
"level": 1
}, {
"name": "Chicken",
"level": 3
}]
}, {
"title": "Test 2",
"type": [{
"name": "Foo",
"level": 2
}]
}, {
"title": "Test 3",
"type": [{
"name": "Baz",
"level": 2
}]
}, {
"title": "Test 4",
"type": [{
"name": "Animal",
"level": 1
}, {
"name": "Dog",
"level": 2
}]
}]
data.forEach((node) => {
k = false;
typechild[node.title] = [];
node.type && node.type.forEach((t, i) => {
if (t.level == 1) {
k = true;
!out[t.name] ? out[t.name] = {
name: t.name,
typechild: typechild[node.title]
} : out[t.name].typechild = out[t.name].typechild.concat(typechild[node.title]);
} else {
typechild[node.title].push(t);
}
if (i == node.type.length - 1 && !k && typechild[node.title].length) {
out['No name'] = out['No name'] || {
name: 'No name',
typechild: []
};
out['No name'].typechild = out['No name'].typechild.concat(typechild[node.title]);
}
});
});
console.log(JSON.stringify(Object.values(out)));

Javascript Loop and filter out the data thats null or empty

I have some data and I need to filter out the data thats null or empty and create a new data list thats filtered.
In this case sometimes "names" array is null so I need that data out.
{
"people": [
{
"id": "2",
"description": "desc here",
"names": [
{
"name": "name here",
},
{
"name": "name here",
}
],
"other": "0"
},
{
"id": "200",
"description": "desc here",
"names": null
"other": "0"
},
{
"id": "64",
"description": "desc here",
"names": [
{
"name": "name here",
},
{
"name": "name here",
}
],
"other": "1"
}
]
}
How can I do this?
You could iterate the arrays and objects recursive until a primitive is found. Then check and return the value.
function copy(object) {
var o;
if (Array.isArray(object)) {
return object.reduce(function (r, a) {
var v = copy(a);
v.names !== null && v.names !== '' && r.push(v);
return r;
}, []);
}
if (object !== null && typeof object === 'object') {
o = {};
Object.keys(object).forEach(function (k) {
o[k] = copy(object[k]);
});
return o;
}
return object;
}
var data = { people: [{ id: "2", description: "desc here", names: [{ id: "345", name: "name here", }, { id: "54", name: "name here", foo: "", }], other: "0" }, { id: "2", description: "desc here", names: null, other: "0" }, { id: "64", description: "desc here", names: [{ id: "87", name: "name here", }, { id: "53", name: "name here", }], other: "1" }] },
result = copy(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var newArray = oldArray.filter(function(v){return v!==''});
new_array=yourObject.people.filter(function(elem){
return elem.names!==null && elem.names!==""
});

Categories

Resources