2017-05-03 141 views
0

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

大多数数据格式为城市,州(美国标准,或多或少)。有些城市分布在较重的人口聚集区和多个城市。

大部分数据看起来像这样(称之为1):

Elkhart, IN 

有人的地方就有多个城市,一个破折号分隔(称之为2):

Hickory-Lenoir-Morganton, NC 

它仍然不是当这些城市处于不同的状态时,这种情况太复杂了(称为3):

Steubenville, OH-Weirton, WV 

这一个给我一个循环;它是有道理的,但它刷新先前格式(称之为4):

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

在该示例中,Bristol在两个VATN。再有就是这个(这个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语句来做这件事的好方法?

回答

1

我会用' - '和','分隔输入,然后删除数组中的空元素。 str_replace之后是explode和array_diff(,array())应该可以做到。 然后确定国家 - 无论是搜索一个清单还是处理校长都认为城市不会有2个大写字母的名字。 现在通过数组进行工作。如果是城市,请保存名称,如果是国家,则将其应用于已保存的城市。紧接着一个国家后,立即清除城市列表。 注意任何异常,并手动重新格式化为不同的输入。

希望这会有所帮助。

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过程,所以速度并不是最重要的。也没有错误检测,这在我的特定情况下起作用。