Home > Blockchain >  Transform array in to object with custom properties
Transform array in to object with custom properties

Time:04-26

I have this array

myarr = [
  '=title1',
  'longText0...',
  'longtText1...',
  '=title2',
  'longTextA...',
  'longtTextB...',
  'longtTextC...'     
];

symbol = indicates that is is a property, next to that is a list of items that belongs to that property

I want to transform that array into object

myObj = {
   title1: [
     'longText0...',
     'longtText1...',   
   ],

   title2: [
     'longTextA...',
     'longtTextB...',  
     'longtTextC...'
   ]
}

I come up with this code so far:

const arrayToObject = (array) =>
   array.reduce((obj, item) => {
     if(item.startsWith('=')) {
       const itemName = item.replace('=', '')
       obj[itemName] = itemName;
     } else {
       
       //add the rest....
     }
 

     return obj
   }, {})


console.log(arrayToObject(myarr))

My challenges so far is that I am not sure how to turn obj[itemName] so I can assign the items to it. Any ideas how to do that?

CodePudding user response:

I wouldn't do that with reduce but with a simple for loop, because you have to carry the itemname over multiple iterations

let o = {}, n = ''; 
for (let k of arr) {
  if (k.startsWith('=')) { 
    n = k.substring(1);
    o[n] = []
  } else {
    o[n].push(k);
  }
}

You can of course also do it with reduce, but you have to put the declaration of itemname outside of the callback

let n = '';
let o = arr.reduce((a, c) => {
  if (c.startsWith('=')) {
    n = c.substring(1);
    a[n] = [];
  } else {
    a[n].push(c);
  }
  return a;
}, {});

Please be aware, there is no error handling, ie the code assumes your array is well structured and the first element in the array must start with =

CodePudding user response:

A reduce based approach which does not depend on outer scope references for keeping track of the currently to be built/aggregated property makes this information part of the reducer function's first parameter, the previousValue which serves as an accumulator/collector object.

Thus, as for the OP's task, this collector would feature two properties, the currentKey and the result, where the former holds the state of the currently processed property name and the latter being the programmatically built result.

// - reducer function which aggregates entries at time,
//   either by creating a new property or by pushing a
//   value into the currently processed property value.
// - keeps the state of the currently processed property
//   by the accumulator`s/collector's `currentKey` property
//   whereas the result programmatically gets build as
//   the accumulator`s/collector's `result` property.

function aggregateEntry({ currentKey = null, result = {} }, item) {
  const key = (item.startsWith('=') && item.slice(1));
  if (
    (key !== false) &&
    (key !== currentKey)
  ) {
    // keep track of the currently processed property name.
    currentKey = key;

    // create a new entry (key value pair).
    result[currentKey] = [];
  } else {
    // push value into the currently processed property value.
    result[currentKey].push(item);
  }
  return { currentKey, result };
}
console.log([
  '=title1',
  'longText0...',
  'longtText1...',
  '=title2',
  'longTextA...',
  'longtTextB...',
  'longtTextC...',
].reduce(aggregateEntry, { result: {} }).result);
.as-console-wrapper { min-height: 100%!important; top: 0; }

CodePudding user response:

The following function will give you the desired results

    function arrayToObject(arr)
{
    let returnObj={};
    for(let i =0; i <arr.length; i  )
    {
        if(arr[i].startsWith('='))
       {
           let itemName = arr[i].replace('=','');
           returnObj[itemName]=[];
           for(let j=i 1; j <arr.length;j  )
           {
               if(arr[j].startsWith('='))
               {
                   break;
               }
               else
                {
                    let value = arr[j];
                    returnObj[itemName].push(value) ;
                }
               
           }
           
       }
    }
    
    return returnObj;
}

CodePudding user response:

Here a version with reduce

const myarr = [
  '=title1',
  'longText0...',
  'longtText1...',
  '=title2',
  'longTextA...',
  'longtTextB...',
  'longtTextC...'     
];


const obj = myarr.reduce((res, el) => {
 if(el.startsWith('=')){
   const key = el.substring(1)
   return {
     data: {
       ...res.data,
       [key]: [],
     },
     key
   }
 }
 return {
  ...res,
   data:{
     ...res.data,
     [res.key]: [...res.data[res.key], el]
   }
 }

}, {
 data: {},
 key: ''
}).data

console.log(obj)

  • Related