将数组转换为具有自定义属性的对象

Transform array into object with custom properties

我有这个数组

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

符号 = 表示这是一个 属性,旁边是属于 属性

的项目列表

我想将该数组转换为对象

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

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

到目前为止我想出了这个代码:

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))

我目前面临的挑战是我不确定如何转向 obj[itemName] 以便我可以将项目分配给它。有什么想法吗?

我不会用 reduce 这样做,而是用一个简单的 for 循环,因为你必须在多次迭代中携带 itemname

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

你当然也可以用reduce来做,但是你必须把itemname的声明放在回调之外

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

请注意,没有错误处理,即代码假定您的数组结构良好并且数组中的第一个元素必须以 =

开头

下面的函数会给你想要的结果

    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;
}

这里是 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)

一个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.

因此,对于 OP 的任务,此收集器将具有两个属性,currentKeyresult,其中前者保存当前处理的 属性 名称的状态后者是以编程方式构建的结果。

// - 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; }

对于 reduce 方法,您不需要将密钥单独保存在某个地方:

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

const res = Object.fromEntries(
  myarr.reduce((acc, item) => {
    if(item.startsWith('='))
      acc.push([item.substring(1), []]);
    else
      acc[acc.length - 1]?.[1].push(item);
    
    return acc;
  }, [])
);

console.log(JSON.stringify( res ));