Reputation: 3641
I have this value:
const sample = [{
name: "name",
value1: 1,
mean: 2,
create: 10,
age: "age",
player1: 20,
player2: 40,
sample: "sample",
player3: 30,
player4: 100,
}];
to be mapped into:
{
name: {
value: 1,
mean: 2,
create: 10
},
age: {
player1: 20,
player2: 40
},
sample: {
player3: 30,
player4: 100
}
}
I know what I can do is to map it manually but my list is around 50 so it's not possible.
Edit:
The key property will be if it's string and the number will be the values in that order
Upvotes: 0
Views: 1804
Reputation: 21
Your description is not clear, however, I think you want to remap a group of properties into a new property, only if key and value is the same.
Moreover, I put a new key = value = "other" and the properties afterwards are grouped under "other", so you don't have to specify all of the keys...
const sample = [{
name: "name",
value1: 1,
mean: 2,
create: 10,
age: "age",
player1: 20,
player2: 40,
}, {
name: "name",
value1: 1,
mean: 2,
create: 10,
age: "age",
player1: 20,
player2: 40,
other: "other",
p2: "ldkdskd",
p1: 10
}];
function remapdata(data) {
const obj = {};
const keys = Object.keys(data);
let lastGroup = undefined;
let i = 0;`enter code here`
while(i < keys.length) {
if(keys[i] === data[keys[i]]) {
obj[keys[i]]= {};
lastGroup=keys[i];
} else if (lastGroup) {
obj[lastGroup][keys[i]] = data[keys[i]];
}
i++;
}
return obj;
}
const mapped = sample.map(remapdata);
console.log(mapped);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Upvotes: 2
Reputation: 13376
Everyone should be aware of that any approach which is going to restructure any object's key-value pair(s) is actually relying on a structure that always has to ensure, for e.g. Object.keys
, a key order that exactly represents the order of any key's creation. Also the environment that creates such objects has to ensure exactly such a viable and reproducible order as well.
If one could generalize that, " ... whenever in a key-value pair key
equals value
, one wants to create a new object assigned to the resampled structure via key
.", one should go with the beneath provided approach as is. Otherwise one has to limit the condition that is responsible for creating new sub-structures to any string type value
which then also does limit the types the original structure is allowed to feature. ...
const sampleList = [{
name: "name",
value1: 1,
mean: 2,
create: 10,
age: "age",
player1: 20,
player2: 40,
sample: "sample",
player3: 30,
player4: 100
}, {
sample: "sample",
player1: 130,
player2: 1100,
name: "name",
value1: 11,
mean: 12,
create: 110,
age: "age",
player3: 120,
player4: 140
}];
function restructureSample(sample) {
const newSample = {};
return Object.entries(sample).reduce((reference, tuple, idx, arr) => {
const [key, value] = tuple;
//if (typeof value === 'string') { // - more generic, but limiting the use cases.
if (key === value) { // - maybe even more precise.
reference = newSample[key] = {};
} else {
reference[key] = value;
}
return (((idx === (arr.length - 1)) && newSample) || reference);
}, newSample);
}
console.log(sampleList.map(restructureSample));
.as-console-wrapper { min-height: 100%!important; top: 0; }
Upvotes: 1
Reputation: 28414
You can use .map
function to iterate over the objects, and keep track of the last key
to add integer-properties to them:
const sample = [
{
name: "name",
value1: 1,
mean: 2,
create: 10,
age: "age",
player1: 20,
player2: 40,
sample: "sample",
player1a: 30,
player2a: 100,
},
{
name: "name",
value1: 11,
mean: 22,
create: 130,
age: "age",
player1: 210,
player2: 430,
sample: "sample",
player1a: 340,
player2a: 1100,
},
{
name: "name",
value: 313,
mean: 421,
create: 23,
age: "age",
player1a: 440,
player2a: 40,
}
];
let lastKey = null;
let mapped = sample.map(elem => {
let obj = { any: {} };
let any = obj.any;
for(var p in elem){
let key = p, value = elem[p];
if(typeof(value)=="string"){
any[key] = {};
lastKey = key;
}else if(typeof(value)=="number"){
if(lastKey)
any[lastKey][key] = value;
else
any[key] = value;
}
}
return obj;
});
console.log(mapped);
Note that you cannot have two same keys (player1
and player2
) since it should be unique.
Upvotes: 0
Reputation: 5853
Use Array.prototype.reduce
to reduce the array and remap
the existing properties into your desired format.
const sample = [
{
name: "name",
value1: 1,
mean: 2,
create: 10,
age: "age",
player1: 20,
player2: 40,
}
];
const result = sample.reduce((acc, { value1, mean, create, player1, player2 }) => {
acc.push({
name: {
value1,
mean,
create
},
age: {
player1,
player2
}
});
return acc;
}, []);
console.log(result);
For dynamic keys you can do something like -
const sample = [
{
name: "name",
value1: 1,
mean: 2,
create: 10,
age: "age",
player1: 20,
player2: 40,
}
];
const keyMapping = {
name: ['value1', 'mean', 'create'],
age: ['player1', 'player2']
};
const result = sample.reduce((acc, curr) => {
const obj = Object.entries(keyMapping).reduce((accumulator, [key, val]) => {
accumulator[key] = val.reduce((r, c) => {
r[c] = curr[c];
return r;
}, Object.create(null));
return accumulator;
}, Object.create(null));
acc.push(obj);
return acc;
}, []);
console.log(result);
Upvotes: 0
Reputation: 4519
You probably want something like this
const sample = [ { name: "name", value1: 1, mean: 2, create: 10, age: "age", player1: 20, player2: 40, }, ];
res = sample.reduce((r, c) => {
let key;
Object.entries(c).forEach((o) => {
(k = o[0]), (v = o[1]);
typeof v == "string" ? ((key = v), (r[v] = {})) : (r[key][k] = v);
});
return r;
}, {});
console.log(res);
Upvotes: 1
Reputation: 4425
To do this the right way, you need to specify properties that will fall under name
and age
in the final object, something like in the following example:
const sample = [
{
name: "name",
value1: 1,
mean: 2,
create: 10,
age: "age",
player1: 20,
player2: 40
},
{
name: "fred",
value1: 3,
mean: 5,
create: 101,
age: "age",
player1: 202,
player2: 401
}
];
const keyValuesMap = {
// `name` property will have `value1`, `mean`, and `create` properties
name: ["value1", "mean", "create"],
// `age` property will have `player1` and `player2` properties
age: ["player1", "player2"]
};
const result = sample.map((item) => {
// map over the `sample` data and get the key/value pairs of each
// item, then use `reduce` to create a new object based on the
// `keyValuesMap` specified above
return Object.entries(item).reduce((accumulator, [key, value]) => {
const name = accumulator.name || {};
const age = accumulator.age || {};
// if value belongs to the `name` property, add to it
if (keyValuesMap.name.includes(key)) {
name[key] = value;
}
// if value belongs to the `age` property, add to it
if (keyValuesMap.age.includes(key)) {
age[key] = value;
}
accumulator.name = name;
accumulator.age = age;
return accumulator;
}, {});
});
console.log("result", result);
References:
Upvotes: 1
Reputation: 4616
Use Array#map for mapping it to the new object-structure inside.
const sample = [
{
name: "name",
value1: 1,
mean: 2,
create: 10,
age: "age",
player1: 20,
player2: 40,
}
];
let result = sample.map(elem => ({
any : {
name: {
value: elem.value1,
mean: elem.mean,
create: elem.create
},
age: {
player1: elem.player1,
player2: elem.player2
}
}
}))
console.log(result);
Upvotes: 1