Home > Mobile >  convert an array to an object of key value pairs
convert an array to an object of key value pairs

Time:03-25

if I have an array of strings like:

['person,item,cost,amount',
  'John,shoes,200,2']

how could I convert this into an object that resembles:

{  
   'John':[  
      {  
         item:'shoes',
         cost:'200',
         amount:'2',
         totalPriceForItems:'400'
      }

CodePudding user response:

If I understand correctly, you may try something like this:

const convert = data => {
  const [columnsText, ...items] = data;
  const columns = columnsText.split(',');
  
  return items.reduce((acc, text) => {
    const { person, ...entries } = Object.fromEntries(text.split(',').map((value, i) => [columns[i], value]));
    entries.totalPriceForItems = String(entries.cost * entries.amount);
    
    if(acc[person]) {
      acc[person].push(entries);
    } else {
      acc[person] = [entries];
    }
    
    return acc;
  }, {});
};

const result = convert([
  'person,item,cost,amount', 
  'John,shoes,200,2', 
  'Bob,glasses,50,3',
  'John,shirts,100,5',
]);

console.log(result);

CodePudding user response:

According to your comment,

I have 8 lines of 'John,shoes,200,2' but with different amounts in the same array. The 'person,item,cost,amount' is only mentioned once at the start of the array

What I understand is that you have a csv with headers and multiple rows. If that is the case, then your data would resemble something like this:

data = [
  'person,item,cost,amount',
  'John,shoes,200,2',
  'Adam,pants,60,1',
  'Kelly,skirt,180,2',
  'John,skirt,150,3'
]

Then you could consider the following approach, that is generic enough to adapt to different headers, and multiple data rows with repeated keys (person names).

// here, you define a function to transform each row of your data,
// like parsing numeric attributes and calculating the totals
function transform(row) {
  row.cost = Number.parseInt(row.cost)
  row.amount = Number.parseInt(row.amount)
  row.total = row.cost * row.amount
  return row
}

// The following logic is generic, and can be used 
// to map and aggregate any kind of csv with headers
hdrs = data.shift().split(',').slice(1)
rows = data.map(r => r.split(',')).reduce((acc, [n, ...kvs]) => 
  ({ ...acc, [n]: [...acc[n] || [], transform(Object.fromEntries(kvs.map((v, i) => [hdrs[i], v])))] }), {})

Output:

{ 
  John: [
    { item: "shoes", cost: 200, amount: 2, total: 400 }, 
    { item: "skirt", cost: 150, amount: 3, total: 450 }], 
  Adam: [
    { item: "pants", cost:  60, amount: 1, total:  60 }], 
  Kelly: [
    { item: "skirt", cost: 180, amount: 2, total: 360 }]
}
  • Related