如何将字符串数组转换为具有多个元素的对象数组

how to transform strin array in to array of objects with multiple elements

我有这个数组:

data: [
  ‘big text 1 here.’,
  ‘big text 2 here followed by list:’,
  '-this is list item;',
  '-this is another list item;',
  ‘big text 3 here followed by list:’,
  '-this is list item;',
  '-this is another list item;',
  '-this is another list item;',
  ‘big text 4 here.’
],

我想把它变成类似这样的东西:

data: [
  { 
   text: ‘big text 1 here.’
   list: []
  },
  { 
   text: ‘big text 2 here followed by list:’
   list: [
     '-this is list item;',
     '-this is another list item;'
   ]
  },
  { 
   text: ‘big text 3 here followed by list:’
   list: [
     '-this is list item;',
     '-this is another list item;',
     '-this is another list item;',
   ]
  },
  { 
   text: ‘big text 4 here.’
   list: []
  },
],

我正在尝试通过这种方式实现这一目标

interface item {
  text: string;
  list: string[];
};

const newArr: item[] = [];

this.item.content.forEach((x, i) => {
  if(x.startsWith('-') && x.endsWith(';')) {
    //this is bullet list, need to add that to the previous item...
  } else {
    newArr.push({ text: x, list: []});
  }
});

我不确定我这样做是否正确,因为我无法想到如何访问 newArr 中的上一个元素;任何想法如何以正确的方式做到这一点?

这是我想要基于该数据的输出:

<p>big text 1 here</p>
<p>big text 2 here followed by list:</p>
<ul>
  <li>this is list item</li>
  <li>this is another list item</li>
</ul>
<p>big text 3 here followed by list</p>
<ul>
  <li>this is list item</li>
  <li>this is another list item</li>
  <li>this is another list item</li>
<p>big text 4 here</p>

只是说您的字符串没有正确的引号,' 不一样, 不适用于字符串。

为此我会使用 Array.reduce

interface DataItem {
    text: string
    list: string[]
}

function isListItem(item: string): boolean {
    return item.startsWith('-') && item.endsWith(';')
}

const transformedData = data.reduce<DataItem[]>((acc, item) => {
    // if item is list item
    if (isListItem(item)) {
        // get last DataItem from acc
        const lastDataItem = acc[acc.length - 1]

        // and use it as list item's parent
        if (lastDataItem) {
            lastDataItem.list.push(item)
        } else {
            console.error(`Parent text not found for list item ${item}`)
        }

        return acc
    }

    // if item is not list item, use it as new parent/DataItem
    const dataItem: DataItem = {
        text: item,
        list: []
    }

    return [...acc, dataItem]
}, [])

Playground link

您可以尝试以下代码段

let data = [
  'big text 1 here.',
  'big text 2 here followed by list:',
  '-this is list item;',
  '-this is another list item;',
  'big text 3 here followed by list:',
  '-this is list item;',
  '-this is another list item;',
  '-this is another list item;',
  'big text 4 here.'
];

function format_array_to_object(data) {
    let new_data = [];
  let previous_data = {};
  data.forEach( function( item, key ){
    if ( item.trim().charAt(0) === '-' ) {
       previous_data.list.push( item );
    } else {
      if ( Object.keys(previous_data).length !== 0 ) {
        new_data.push(previous_data);
        previous_data = {};
        let current_elem = { text: item, list:[] };
        previous_data = current_elem;
      } else {
        let current_elem = { text: item, list:[] };
        previous_data = current_elem;
      }

      if ( ( key + 1 ) === data.length ) {
        new_data.push(previous_data);
      }

    }
  } );
  return new_data;
}

console.log(format_array_to_object(data));

我会选择 ngTemplateOutlet 选项来根据您的列表数组生成 li。

<ul *ngFor="let item of data">
   <ng-container
       *ngTemplateOutlet="
          !(item.startsWith('-') && item.endsWith(';')) ? ulTemplate : bulletItem;
         context: { $implicit: item }
     "
     >
   </ng-container>
</ul>

<ng-template #ulTemplate let-item>
   <li>{{ item }}</li>
</ng-template>

<ng-template #bulletItem let-item>
  <ul>
    <li>{{ item }}</li>
  </ul >
</ng-template>

现在,这样您就可以根据您的起始字符重新获得正确的ng-template。 在此 link Stackblitz Link

中完成演示