【问题标题】:how to parse & format content of text into object如何将文本内容解析并格式化为对象
【发布时间】:2013-11-27 02:51:51
【问题描述】:

正如标题所说,我需要从具有某些字段的长文本中提取内容。

我有如下文字

Name: David Jones
Office Address: 148 Hulala Street Date: 24/11/2013
Agent No: 1234,
Address: 259 Yolo Road Start Date: 22/11/2013 Due Date: 29/11/2013
Type: Human Properties: None Ago: 29

我有这些标签用于文本中的特定字段

Name, Office Address, Date, Agent No, Address, Type, Properties, Age

而我想要得到的结果是

Name: 'David Jones',
Office Address: '148 Hulala Street',
Date: '24/11/2013',
Agent No: '1234',
Address: '259 Yolo Road',
Type: 'Human'
Properties: 'None',
Age: ''

已经完全解析了每个字段的内容。 Important thing to note here is the original text can possibly have typo (E.g., Ago instead of Age) and extra fields that do not exist in the list of labels (E.g., Start Date and Due Date do not exist in the label list)。因此代码将忽略任何不匹配的文本并尝试仅查找匹配的结果。

我尝试通过遍历每一行的循环来解决这个问题,检查一行是否包含该字段,并查看该行是否还包含更多字段。

目前我有以下代码。

structure = ['Name','Office Address','Date','Agent No','Address','Type','Properties','Age'];
obj = {};
for (i = 0; i < textLines.length; i++) {
  matchingFields = [];
  for (j = 0; j < structure.length; j++) {
    if (textLines[i].indexOf(structure[j] + ':') !== -1) {
      if (matchingFields.length === 0 && textLines[i].indexOf(structure[j] + ':') === 0) {
        matchingFields.push(structure[j]);
        structure.splice(structure.indexOf(structure[j--]), 1);
      } else if (textLines[i].indexOf(structure[j] + ':') > textLines[i].indexOf(matchingFields[matchingFields.length-1])) {
        matchingFields.push(structure[j]);
        structure.splice(structure.indexOf(structure[j--]), 1);
      }
    }

    for (j = 0; j < matchingFields.length; j++) {
      if (j !== matchingFields.length-1) {
        obj[matchingFields[j]] = textLines[i].slice(textLines[i].indexOf(matchingFields[j]) + matchingFields[j].length, textLines[i].indexOf(matchingFields[j+1]));
      } else {
        obj[matchingFields[j]] = textLines[i].slice(textLines[i].indexOf(matchingFields[j]) + matchingFields[j].length);
      }

      obj[matchingFields[j]] = obj[matchingFields[j]].replace(':', '');
      if (obj[matchingFields[j]].indexOf(' ') === 0) {
        obj[matchingFields[j]] = obj[matchingFields[j]].replace(' ', '');
      }
      if (obj[matchingFields[j]].charAt(obj[matchingFields[j]].length-1) === ' ') {
        obj[matchingFields[j]] = obj[matchingFields[j]].slice(0, obj[matchingFields[j]].length-1);
      }
    }
  }

在某些情况下它可以正常工作,但 'Office Address: ''Address: ' 的现有值 'Office Address:' 进入 'Address:'。此外,代码看起来又乱又丑。也似乎是一种蛮力。

我想应该有更好的方法。例如使用正则表达式或类似的东西。但没有外部库。

如果您有任何想法,我将不胜感激。

【问题讨论】:

    标签: javascript regex string parsing


    【解决方案1】:

    假设属性由换行符分隔,您可以使用以下方法创建一个将每个属性映射到其值的对象:

    var str = "Name: David Jones\nOffice Address: 148 Hulala Street\nDate: 24/11/2013\nAgent No: 1234,\nAddress: 259 Yolo Road\\nType: Human Properties: None Age: 29";
    var output = {};
    
    str.split(/\n/).forEach(function(item){ 
        var match = (item.match(/([A-Za-z\s]*):\s([A-Za-z0-9\s\/]*)/));
        output[match[1]] = match[2];
    });
    
    console.log(output)
    

    【讨论】:

    • 不幸的是,我拥有的初始信息是我的问题中的第一个文本框和每个属性的标签。但我想我可以通过在每个属性之前插入换行符并执行您的代码来解决这个问题。谢谢,我现在就试试。
    • 哦,我忘记了我的真实代码与问题的文本不同...示例是随机组成的,实际文本可能包含错误的字段(列)名称。这就是我很难解析的原因。我会发布另一个问题..
    • 让它像我之前的评论和你的代码一样工作! match = (item.match(/(.*):(.*)/)); 更改了正则表达式,因为它也可能包含一些特殊字符。谢谢!
    【解决方案2】:

    这可能会有所帮助:

    > a.substr(a.indexOf("Name"), a.indexOf("Office Address")).split(":")
    ["Name", " David Jones "]
    

    【讨论】:

      猜你喜欢
      • 2013-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-10
      • 1970-01-01
      相关资源
      最近更新 更多