php - 如何从 csv 数据中对大型多维数组进行排序?
问题描述
我正在导入一个可能有大约 100,000 行的 csv。每行有 5 列。每行的第一列将有一个句子,其他 4 列有数值。我需要遍历 csv 数据并从每一行中获取每个单词并将其作为它自己的行添加到新数组中。例如:
| big red truck | 5 | 2 | 5 | 1 |
| small red truck | 4 | 2 | 0 | 0 |
| big fast truck | 3 | 2 | 4 | 1 |
变成
| truck | 12 | 6 | 9 | 2 |
| red | 9 | 4 | 5 | 1 |
| fast | 3 | 2 | 4 | 1 |
| small | 4 | 2 | 0 | 0 |
这就是我目前正在做的事情。它适用于较小的文件,但在大约 50,000 行时我遇到了问题并开始恢复服务器错误。
function get_csv_terms($csvdata){
$terms = array();
$csv_rows = count($csvdata);
$x = 0;
//get terms
while($x <= $csv_rows){
$groupTerm = explode(' ', $csvdata[$x][0]);
foreach( $groupTerm as $term ){
if($term != NULL){
if(!in_array($term, $terms)){
$terms[] = $term;
}
}
}
$x++;
}
return $terms;
}
//filter csv and create data for table output
function filter_csv($csvdata){
$sortedData = array();
$csv_rows = count($csvdata);
$terms = get_csv_terms($csvdata);
$terms_count = count($terms);
$x = 0;
while($x <= $terms_count){
$y = 0;
while($y <= $csv_rows){
$termWords = explode(" ", $csvdata[$y][0]);
$termWordCount = count($termWords);
$z = 0;
while($z <= $termWordCount){
if($terms[$x] != NULL){
if($termWords[$z] == $terms[$x]){
$sortedData[$terms[$x]][0] += intval($csvdata[$y][1]);
$sortedData[$terms[$x]][1] += floatval($csvdata[$y][2]);
$sortedData[$terms[$x]][2] += floatval($csvdata[$y][3]);value
$sortedData[$terms[$x]][3] += floatval($csvdata[$y][4]);
}
}
$z++;
}
$y++;
}
$x++;
}
return $sortedData;
}
解决方案
正如评论中提到的那样,解决方案应该是足够增加内存限制(如果可能的话),或者减少数据重复并切换到一次处理 CSV 一条记录以减少内存使用量。
还有一种可能是,使用定义的对象类可以为您提供更好的内存效率,如果不仅仅是更好的代码可读性的话。例如,你可以试试这个:
class Term
{
// Instance properties
public $UsageCount = 0;
public $Weight = 0.00;
public $Value = 0.00;
public $OtherFloat = 0.00;
// -----------------------
// Term dictionary
private static $_terms = array();
public static Get($term)
{
if(!isset($_terms[$term]))
{
$_terms[$term] = new Term();
}
return $_terms[$term];
}
public static GetAll()
{
return $_terms;
}
}
在您的 CSV 循环中:
$termWords = explode(" ", $csvdata[$y][0]);
...
foreach($termWords as $termWord)
{
$Term = Term::Get($termWord);
$Term->UsageCount += intval($csvdata[$y][1]);
$Term->Weight += floatval($csvdata[$y][2]);
$Term->Value += floatval($csvdata[$y][3]);
$Term->OtherFloat += floatval($csvdata[$y][4]);
}
最新版本的 PHP(7 和更高版本)在对象的内存效率方面非常出色。根据您可能拥有的其他属性和代码,面向对象的方法可以提供很多不错的好处(例如,通过引用自动传递、更易于阅读和维护代码、内存效率、清晰的默认值、数据管理、 ETC...)。
推荐阅读
- git - Git 工作流程建议
- sqlite - 将csv数据导入sqlite时,是否有强制某些数据类型的通用方法?
- php - 使用 passthru() 下载文件会导致文件损坏/修改
- python - 正确使用 Keras 的分类交叉熵损失
- lambda - 使用另一个内联 lambda 参数调用内联 lambda
- c# - Unit Testing a Service without a return type
- python - How to prettyprint as hex a pyasn1 octect string that is printed as ascii
- postgresql - Entity Framework Core code first default values for PostgreSQL
- ios - iOS 11:致命异常:NSInternalInconsistencyException requestFocusAtPoint:在没有输入设备时调用
- linux - 使用 Python 从 linux 执行窗口应用程序