【问题标题】:PHP - strtok(), associative array relationshipPHP - strtok(),关联数组关系
【发布时间】:2016-12-14 21:50:59
【问题描述】:

我对 PHP 中的 Strtok() 函数非常熟悉,而且过去让该函数对字符串正常工作没有任何问题。但是,我目前必须阅读一个 .csv 文本文件(我已经成功完成),其中每行由 6 个字段组成,如下所示:姓氏、名字、地址、城市、地区、邮政编码\r\n

我必须使用 Strok() 将这些按分隔符拆分并将单词标记为字段(即最后一个、第一个、地址等)。我计划使用一个以姓氏作为主键的关联数组,这样我就可以将数据插入到一个 HTML 表中,该表已创建并正在工作。我现在的问题是正确拆分文件,因为它有大约 200 行由这 6 个字段组成,并将字符串正确存储为数组的字段,因此数据结构是我遇到问题的地方。到目前为止,这是我所拥有的:

    $inputFile = fopen("input.csv","r");
    $delimiters = ",";
    $token = strtok($inputFile, $delimiters);
    $n=1;

    while ($token){
      echo "Token $n: $token <br>";
      $token = strtok($delimiters);
      $n++;
    }

显然,表是在它下面创建的,但由于我还没有完成数据结构,所以我没有它的字段。我认为我的令牌循环对于这个问题可能是不正确的,但我从书中的一个早期示例中提取了一些内容,并在我的令牌过程有效但文件结构不同的地方进行了练习。感谢您对此的任何指导或帮助。

【问题讨论】:

  • CSV 的示例行是什么?您从哪里获得这些“单词”以用作关联数组键?
  • 基本上每一行都保存这6个值,然后返回到下一个。这里有两个例子:
  • SELBY,AARON,1519 Santiago de los Caballeros Loop,Mwene-Ditu,East Kasai,22025 GOOCH,ADAM,230 Urawa Drive,Adoni,Andhra Pradesh,2738
  • PHP 已经内置了 parsing csv files 的函数。为什么不使用这些?
  • 有两种很好的方法可以做到这一点,令牌不是其中之一。

标签: php arrays token strtok


【解决方案1】:

PHP中有CSV函数,比如fgetcsv,所以重新发明轮子确实是错误的方法。

请注意,在您的代码中,您实际上并没有读取文件的内容,因为您只获得了一个文件指针。

如果您确实需要使用 strtok 执行此操作,并且您的 CSV 很简单,因为它没有可能嵌入分隔符的带引号的字符串,您可以使用:

  • file_get_contents() 读取一个字符串中的文件内容。当然,file() 会让您更轻松,因为它已经拆分了行。但我假设如果您不允许使用 CSV 函数,那么这也不会。

  • strtok 用于获取字段,但在循环结束时,而不是在开始时,因为使用双参数的初始调用已经检索到循环之前的第一个值。

    李>

代码:

$input = file_get_contents("input.csv");
$delimiters = ",\n\r";

$token = strtok($input, $delimiters);
$result = [];
$row = [];
while ($token){
    echo "Token $token <br>";
    $row[] = $token;
    if (count($row) == 6) { // write record
        $result[] = $row;
        $row = [];
    }
    $token = str_replace('\r', '', strtok($delimiters));
}

print_r($result);

请注意,这不会创建关联数组。如果您需要,请使用以下代码:

 $columns = ['last', 'first', 'address1', 'address2', 'address3', 'zip'];

然后在您的循环中,将$row[] = $token 替换为:

        $row[$columns[count($row)]] = $token;

您可以看到该版本在 eval.in 上运行。您在 cmets 中提供的数据的输出是:

Array (
    [0] => Array (
        [last] => SELBY
        [first] => AARON
        [address1] => 1519 Santiago de los Caballeros Loop
        [address2] => Mwene-Ditu
        [address3] => East Kasai
        [zip] => 22025
    )
    [1] => Array (
        [last] => GOOCH
        [first] => ADAM
        [address1] => 230 Urawa Drive
        [address2] => Adoni
        [address3] => Andhra Pradesh
        [zip] => 2738
    )
)

同样,这是不可取的。你应该使用fgetcsv。这也可以更好地处理可能包含逗号、双引号甚至换行符的字符串。

【讨论】:

  • 谢谢,这绝对让我走上了正确的道路。我也完全理解它的问题,因为我找到了几种无缝的方法来做到这一点。出于某种原因,我的教授决定使用 .csv 文件来显示令牌的功能,但我没有这样做。一个问题:这在我的表格中显示为空白邮政字段,但是当我打印我的结果时它们显示一个标记。这可能与 count($row) 部分有关吗?
  • 我没有看到这样的问题。我在答案中添加了代码链接,您可以在其中检查 $result 数组的内容是否正确并包含邮政编码。可能您在生成表格的代码中还有另一个问题。你可以随时提出一个新的问题。
【解决方案2】:

好吧,我本来打算跳过这个问题,因为fgetcsv(),但我很无聊:

$lines = file($inputFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$delimiters = ",";

foreach($lines as $line) {
    $values = array(strtok($line, $delimiters));
    while($token = strtok($delimiters)){
        $values[] = $token;
    }
    $result[] = $values;
}
  • 将文件行读入数组
  • 循环获取每一行并将该行的第一个标记放入值数组中
  • 循环该行并获取所有标记并添加到值数组中
  • 将值数组添加到结果数组

我添加了一个array_combine(),因为您谈到了关联数组。如果需要,您可以使用类似的东西:

    $result[] = array_combine(array('last name',
                                    'first name',
                                    'address',
                                    'city',
                                    'district',
                                    'postal code'), $values);

如果您希望 last name 成为每个结果行的键,这是不可取的,因为键是唯一的,我认为您不能保证姓氏是唯一的:

    $result[$values[0]] = $values;
    //or to remove it from the array but use as the key
    $result[array_unshift($values)] = $values;

【讨论】:

  • 这对于那些仍然错误的事情需要做很多工作,因为"Spaced Out",2,"This ""Thing""" 是有效的 CSV,具体取决于您对“有效”和“CSV”的定义。
  • 是的,这非常适合解析严格的逗号分隔值,但不能解析 CSV 文件。
  • 我今天看了很多固有的 CSV 助手,但是在尝试之后,我仍然被告知尝试使用令牌功能,所以这显然不是一个好方法。由于它仅由逗号分隔,因此它适用于这一任务。不过,感谢大家的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-31
  • 2011-07-11
  • 2016-10-07
  • 1970-01-01
  • 1970-01-01
  • 2021-05-10
  • 2014-08-09
相关资源
最近更新 更多