Hi guys I get confused trying to qcheave this, so any help would be great!
I have two arrays from which I need a specific object. Source arrays:
1-Types (1D): ['dev', 'env', 'othr']
2-Services (2D): (3) [Array(3), Array(4), Array(6)]
Array(3)
0: "1':'Option 11'"
1: "2':'Option 12'"
2: "3':'Option 13'"
Array(4)
0: "5':'Option 21'"
1: "6':'Option 22'"
2: "7':'Option 23'"
3: "4':'Option 24'"
Array(6)
0: "8':'Option 31'"
1: "9':'Option 32'"
2: "10':'Option 33'"
3: "11':'Option 34'"
4: "12':'Option 35'"
5: "13':'Option 36'"
The desired outcome is this structure:
servData = {
"dev": {
"1": "Option 11",
"2": "Option 12"
"3": "Option 13"
},
"env": {
"4": "Option 21",
"5": "Option 22"
"6": "Option 23",
"7": "Option 24"
},
"othr": {
"8": "Option 31",
"9": "Option 32"
"10": "Option 33",
"11": "Option 34"
"12": "Option 35",
"13": "Option 36"
}
};
CodePudding user response:
Use this:
const itemNames = ['dev', 'env', 'othr']
const items = [
[ "1':'Option 11'",
"2':'Option 12'",
"3':'Option 13'"
],
[
"5':'Option 21'",
"6':'Option 22'",
"7':'Option 23'",
"4':'Option 24'"
],
[
"8':'Option 31'",
"9':'Option 32'",
"10':'Option 33'",
"11':'Option 34'",
"12':'Option 35'",
"13':'Option 36'"
]
]
const value = itemNames.map((value, index) => ({ index, value})).reduce((p, el) => {
p[el.value]={}
items[el.index].forEach(e=>{
let [op,...va] =e.split(':');
va=va.join(':').split('')
va.splice(0,1)
va.pop()
const ar=va.join(':');
p[el.value][parseInt(op)]=ar;
})
return p;
}, {})
console.log(value);
CodePudding user response:
The OP's provided array of stringified entries seems to be mal-formatted ... e.g. "1':'Option 11'"
, with either a missing or a dispensable single quote for the key
part, instead of "'1':'Option 11'"
(with single quotes) or "1:'Option 11'"
(without single quotes for the key part).
Because of that the beneath presented approach uses a capturing regex like /^'?(?<key>\d )'?:'?(?<value>.*?)'?$/
in order to sanitize (or rather be agnostic to) each provided string based key
-value
configuration.
The approach itself makes use of Array.prototype.reduce
twice.
The outer reduce
does process the list of property or item names as propertyName
together with a passed entries config
which features each property name related array of stringified key-value pairs.
The inner reduce
does process such an array, retrieves key
and value
from the string and, based on this data, assigns a new entry to the value which, within the outer reduce
, gets assigned to the newly created propertyName
related entry.
function createEntryFromKeyAndEntriesConfig(
{ config = [], result = {} },
propertyName,
idx,
) {
// see ... [https://regex101.com/r/DQbrRM/1]
const regXKeyValue =
/^'?(?<key>\d )'?:'?(?<value>.*?)'?$/;
result[propertyName] = config[idx]
.reduce((obj, entryString) => {
const { key = '', value = '' } = regXKeyValue
.exec(entryString)
?.groups;
obj[key] = value;
return obj;
}, {});
return { config, result };
}
const entriesConfig = [[
"1':'Option 11'",
"2':'Option 12'",
"3':'Option 13'",
], [
"5':'Option 21'",
"6':'Option 22'",
"7':'Option 23'",
"4':'Option 24'",
], [
"8':'Option 31'",
"9':'Option 32'",
"10':'Option 33'",
"11':'Option 34'",
"12':'Option 35'",
"13':'Option 36'",
]];
const propertyNames = ['dev', 'env', 'othr'];
const { result: servData } = propertyNames
.reduce(createEntryFromKeyAndEntriesConfig, {
config: entriesConfig,
result: {},
});
console.log({ servData });
.as-console-wrapper { min-height: 100%!important; top: 0; }
CodePudding user response:
Your data did need some cleanup.
Use Array#map
and Array#reduce
as follows:
const keys = ['dev', 'env', 'othr'],
input = [ [ "1:'Option 11'", "2:'Option 12'", "3:'Option 13'" ], [ "5:'Option 21'", "6:'Option 22'", "7:'Option 23'", "4:'Option 24'" ], [ "8:'Option 31'", "9:'Option 32'", "10:'Option 33'", "11:'Option 34'", "12:'Option 35'", "13:'Option 36'" ] ],
output = keys.map(
(key,i) =>
({
[key]: input[i].reduce(
(acc,cur) =>
({...acc,[cur.split(':')[0]]:cur.split(':')[1]}),{})
})
);
console.log( output );