解析混合分隔符数据集

时间:2017-05-03 22:55:03

标签: php

我有一个源文件,其中包含一些我需要解析的格式的数据。我正在编写一个必须与其他数据匹配的ETL过程。

大多数数据的格式为城市,州(美国标准,或多或少)。一些城市分布在人口较多的地区,多个城市相结合。

大部分数据都是这样的(称之为1):

Elkhart, IN

有些地方有多个城市,用破折号分隔(称之为2):

Hickory-Lenoir-Morganton, NC

当城市处于不同的状态时,它仍然不会太复杂(称之为3):

Steubenville, OH-Weirton, WV

这个人把我扔了一圈;它有意义,但它刷新以前的格式(称之为4):

Kingsport, TN-Johnson City, TN-Bristol, VA-TN

在该示例中,BristolVA同时包含TN。然后是这个(称之为5):

Mayagüez/Aguadilla-Ponce, PR

我可以用破折号替换斜线并处理与前一个示例相同的斜杠。这包含一个变音符号,我的其余数据都是不含变音符号的。我很好地剥离了变音符号,这在PHP中似乎有些简单。

然后是我的最后一个例子(称之为6):

Scranton--Wilkes-Barre--Hazleton, PA

城市名称包含破折号,因此城市名称之间的分隔符是双破折号。

我想要产生的是,给定上述任何一个示例和几百个遵循相同格式的其他行,每个都有一个[[city, state],...]数组,因此我可以将它们转换为SQL。例如,解析4将产生:

[
    ['Kingsport', 'TN'],
    ['Johnson City', 'TN'],
    ['Bristol', 'VA'],
    ['Bristol', 'TN']
]

我正在使用标准的PHP安装,我有preg_match等等,但没有PECL库。订单并不重要。

如果没有大量的if-then陈述,有什么好的方法可以做到这一点吗?

2 个答案:

答案 0 :(得分:1)

我会用'-'s和'分隔输入,然后删除数组中的空元素。 str_replace后跟explode和array_diff(,array())应该做的伎俩。 然后确定国家 - 搜索列表或处理校长,城市不具有2个大写字母名称。 现在通过数组工作。如果是城市,请保存名称,如果是州,则将其应用于已保存的城市。当您在州之后立即获得城市时,清除城市列表。 注意任何异常并手动重新格式化为不同的输入。

希望这有帮助。

答案 1 :(得分:0)

对于任何有兴趣的人,我都从@mike那里得到了答案并提出了这个问题:

function SplitLine($line) {
  // This is over-simplified, just to cover the given case.
  $line = str_replace('ü', 'u', $line);

  // Cover case 6.
  $delimiter = '-';
  if (false !== strpos($line, '--'))
    $delimiter = '--';

  $line = str_replace('/', $delimiter, $line);

  // Case 5 looks like case 2 now.

  $parts = explode($delimiter, $line);
  $table = array_map(function($part) { return array_map('trim', explode(',', $part)); }, $parts);

  // At this point, table contains a grid with missing values.

  for ($i = 0; $i < count($table); $i++) {
    $row = $table[$i];

    // Trivial case (case 1 and 3), go on.
    if (2 == count($row))
      continue;

    if (preg_match('/^[A-Z]{2}$/', $row[0])) {
      // Missing city; seek backwards.
      $find = $i;
      while (2 != count($table[$find]))
        $find--;
      $table[$i] = [$table[$find][0], $row[0]];
    } else {
      // Missing state; seek forwards.
      $find = $i;
      while (2 != count($table[$find]))
        $find++;
      $table[$i][] = $table[$find][1];
    }
  }
  return $table;
}

它不漂亮而且速度很慢。它确实涵盖了我的所有情况,因为我正在进行ETL过程,速度并不是最重要的。还没有错误检测,这在我的特定情况下有效。