Reputation: 16793
I have a set of values in an array where each value has an ID and LABEL.
const data = [
{ID: 0, LABEL: 'turbo'},
{ID: 1, LABEL: 'classic'},
{ID: 7, LABEL: 'unknown'}
];
const hashMap = data.reduce((result, item) => {
return { ...result, [ item.ID ] : item.LABEL };
}, {});
const hashMapJson = JSON.stringify(hashMap);
console.log('hashMap', hashMap);
console.log('hashMapJson', hashMapJson);
But if I have the following json object where key is slightly different, it does not handle of course. I wonder how I could able to make the above solution in more generic to tackle different inputs.
const data = [
{K_ID: 0, K_LABEL: 'turbo'},
{L_ID: 1, K_LABEL: 'classic'},
{S_ID: 7, K_LABEL: 'unknown'}
];
Upvotes: 1
Views: 310
Reputation: 11574
You can make create an extractIdLabel
function that tries to guess the keys for ID and Label respectively. You can use regex (via string.prototype.match
) or other tools to make it as robust as required.
In the example below,
1) it looks for the keys 'id' and 'label'. e.g. {id: 0, label: 'zero'}
2) If one or both are not found, then it looks for keys containing the strings 'id' and 'label'. e.g. {x_id: 0, y_label_z: 'zero'}
3) If still one of them is not found, but the other is found, and the item has 2 keys, it uses the unused key for the not-found one. e.g. {id: 0, obviously_not_id_so_must_be_L_a_b_e_l: 'zero'}
const data = [
{K_ID: -1, K_LABEL: 'turbo'},
{L_ID: 1, K_LABEL: 'classic'},
{S_ID: 7, K_LABEL: 'unknown'},
{ID: 10, LABEL: 'ten', garbage: 'garbage', bad_label: 'bad_label'},
{KEY: 11, X_LABEL: 'eleven'},
{Y_ID: 12, VALUE: 'twelve'},
{id: 0, obviously_not_id_so_must_be_L_a_b_e_l: 'zero'}
];
let extractIdLabel = item => {
let keys = Object.keys(item);
let id = keys.find(key => key.toLowerCase() === 'id') ||
keys.find(key => key.toLowerCase().includes('id'));
let label = keys.find(key => key.toLowerCase() === 'label') ||
keys.find(key => key.toLowerCase().includes('label'));
if (keys.length === 2 && !id ^ !label)
if (!id)
id = keys.find(key => key !== label);
else
label = keys.find(key => key !== id);
return [item[id], item[label]];
};
const hashMap = data.reduce((result, item) => {
let [id, label] = extractIdLabel(item);
return {...result, [id]: label};
}, {});
const hashMapJson = JSON.stringify(hashMap);
console.log('hashMap', hashMap);
console.log('hashMapJson', hashMapJson);
Upvotes: 1
Reputation: 28445
You can try following using String.endsWith
const data = [{K_ID: 0, K_LABEL: 'turbo'},{L_ID: 1, K_LABEL: 'classic'},{S_ID: 7, K_LABEL: 'unknown'}];
const hashMap = data.reduce((result, item) => {
const temp = Object.keys(item);
const key = temp[0].endsWith("_ID") ? 0 : 1; // check for 1st key ending with _ID
const value = +!key; // if key is 1, value be 0 and other way around
result[item[temp[key]]] = item[temp[value]];
return result;
}, {});
const hashMapJson = JSON.stringify(hashMap);
console.log(hashMapJson);
Upvotes: 2
Reputation: 418
You could change your hashMap function to something like the following :
const data = [{K_ID: 0, K_LABEL: 'turbo'},{L_ID: 1, K_LABEL: 'classic'},{S_ID: 7, K_LABEL: 'unknown'}];
const hashMap = data.reduce((result, item) => {
let id
let label
Object.keys(item).forEach((key) => {
if (key.includes('ID')) {
id = key
} else if (key.includes('LABEL')) {
label = key
}
})
return { ...result, [ item[id] ] : item[label] };
}, {});
console.log( hashMap );
This is assuming your data set you are passing (data
) is similar the the one in the example you provided. As long as a key contains ID, it'll make that the id key and as long as a key contains LABEL it will make that the key for the LABEL
Upvotes: 2
Reputation: 386522
You could take a function for finding a similar key of the object.
const
getSimilarKey = (object, key) => Object.keys(object).find(k => k.toLowerCase().includes(key.toLowerCase())),
data = [{ K_ID: 0, K_LABEL: 'turbo' }, { L_ID: 1, K_LABEL: 'classic' }, { S_ID: 7, K_LABEL: 'unknown' }],
key = 'id',
value = 'label',
result = Object.assign(
{},
...data.map(o => ({ [o[getSimilarKey(o, key)]]: o[getSimilarKey(o, value)] }))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
With upcoming Object.fromEntries
const
getSimilarKey = (object, key) => Object.keys(object).find(k => k.toLowerCase().includes(key.toLowerCase())),
data = [{ K_ID: 0, K_LABEL: 'turbo' }, { L_ID: 1, K_LABEL: 'classic' }, { S_ID: 7, K_LABEL: 'unknown' }],
key = 'id',
value = 'label',
result = Object.fromEntries(data.map(o => ({ [o[getSimilarKey(o, key)]]: o[getSimilarKey(o, value)] })));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 667
It really depends of your data model, but this should work...
const data = [
{K_ID: 0, K_LABEL: 'turbo'},
{L_ID: 1, K_LABEL: 'classic'},
{S_ID: 7, K_LABEL: 'unknown'}
]
const hashMap = data.reduce((ac, cv) => {
const keys = Object.keys(cv)
let id, label
keys.forEach(key => {
if(key.endsWith('_LABEL'))
label = cv[key]
else if(key.endsWith('_ID'))
id = cv[key]
})
if(id !== undefined && label !== undefined)
ac[id] = label
return ac
}, {})
console.log(hashMap)
Upvotes: 2