如何将字符串拆分为对象数组

3

我想要分解这个字符串:

data=

1.

Title: The Definitive Guide
Copy: There’s no way around it, 
URL: http://www.schools
Date: 6/7/17

2.

Title: Using 
Copy: Today’s fast
URL: https://blog
Date: 6/16/17
3.

Title: 4 Ways 
Copy: Let’s state
URL: https://www.
Date: 6/20/17

在这种情况下,将其转换为长度为3的数组(对应上述编号之一)。每个数组项应该是一个对象,其中包含以下属性:title,copy,url,date。
我尝试过这种方法:
for(let i=0; i<3; i++) {

    arr[i] =temp.split(i+2 + ".");
    temp=temp.slice(0, arr[i].length);


};

也许有一种更简单的字符串方法。在过去SO发布的问题中没有找到类似的东西。

当你接收到那个字符串时,它具体是什么样子? - Chris
这里没有简单的内置方法来解析你展示的数据格式。你可以编写自定义解析代码,或者让提供输入的人遵守更受欢迎的标准(如JSON)。 - StriplingWarrior
1
请更新问题并包含一个 **[mcve]**。 - Reinstate Monica Cellio
2个回答

2
这需要完成很多事情:
  • 分成行
  • 过滤掉无意义的行
  • 每4个一组划分
  • 从每组创建一个对象
以下是我的方法,使用了chunkobjectFromPairs来自30secondsofcode(声明:我是该项目/网站的维护者),以及大量Array方法:

var data = `

1.

Title: The Definitive Guide
Copy: There’s no way around it, 
URL: http://www.schools
Date: 6/7/17

2.

Title: Using 
Copy: Today’s fast
URL: https://blog
Date: 6/16/17
3.

Title: 4 Ways 
Copy: Let’s state
URL: https://www.
Date: 6/20/17
`;

const chunk = (arr, size) =>
  Array.from({
      length: Math.ceil(arr.length / size)
    }, (v, i) =>
    arr.slice(i * size, i * size + size)
  );

const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {});


const dataArr = chunk(
  data.trim().split('\n')
  .filter(v => v.trim().indexOf(':') !== -1)
  .map(x => {
    let t = x.split(':');
    return [t[0], t.slice(1).join(':')].map(v => v.trim())
  }), 4
 ).map(o => objectFromPairs(o));
console.log(dataArr);


1
@OliverRadini 已修复! - Angelos Chalaris
1
@AngelosChalaris - 我认为这并不真正有效,最终你会得到一个四元素数组,并且对象的属性开始在最后几个对象上失效。 - Chris
@Chris 对不起,我的错,我一次分块了3行,而不是4行。 - Angelos Chalaris

2

我建议逐行阅读这段内容。每一行都可能是数字和点、空格或者数据,这很容易通过循环实现,而无需涉及复杂的正则表达式:

data=`

1.

Title: The Definitive Guide
Copy: There’s no way around it, 
URL: http://www.schools
Date: 6/7/17

2.

Title: Using 
Copy: Today’s fast
URL: https://blog
Date: 6/16/17
31.

Title: 4 Ways 
Copy: Let’s state
URL: https://www.
Date: 6/20/17
`
let current, final = []
data.split('\n').forEach(line => {
  if (/^\d+\./.test(line)) final.push(current = {}) // new block
  else if (/\S/.test(line)){                        // some data
    let split = line.indexOf(":")
    let key = line.slice(0, split)
    let val = line.slice(split +1)
    current[key] = val.trim()
  }
})
console.log(final)

假设数据是干净的。如果存在可能是非数据行的杂乱行,那么您需要进行更多的工作,但我认为基本思路仍然有效。


1
比起我提供的解决方案,这个更加优雅且易于理解。老实说,我肯定更喜欢这个。 - Angelos Chalaris
最大的假设是数据将被包装在模板文字中。如果不是这样,而是一个长字符串,会发生什么? - Chris
@Chris 我不太确定一个带有换行符的长字符串与这个模板字面量有什么不同 - 它们仍然只是字符串。你能澄清一下吗? - Mark
@MarkMeyer - 如果数据是这样的:“1.标题:The Definitive Guide 复制:无法避免,URL:http://www.schools 日期:6/7/17 2.标题:Using 复制:今天的快速 URL:https://blog 日期:6/16/17 3.标题:4种方法 复制:让我们声明URL:https://www 日期:6/20/17”--你的解决方案正在寻找换行符,但没有换行符。你的解决方案仍然能够处理这些数据吗? - Chris
@Chris,不是的。这取决于数据是否像OP中一样在单独的行上。但是,无论是像上面那样的模板文字还是像\n1.\n\nTitle: The Definitive Guide\nCopy: There’s no way around it,这样的字符串都不是问题。 - Mark

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接