5

data.csv を検討してください。

"1","2","3","4"
"5","6","7","8"
"9","10","11","12"
"13","14","15","16"
"17","18","19","20"
"21","22","23","24"
"25","26","27","28"
"29","30","31","32"
"33","34","35","36"

この CSV を読み取り、n 番目ごとに連結する必要があります。たとえば、3 行ごとに連結する必要があります。したがって、望ましい出力は次のとおりです。

array (
  [0] => 1,2,3,4,13,14,15,16,25,26,27,28    // row 1, 4 and 7
  [1] => 5,6,7,8,17,18,19,20,29,30,31,32    // row 2, 5 and 8
  [2] => 9,10,11,12,21,22,23,24,33,34,35,36 // row 3, 6 and 9
)

n を変数にする必要があるため、たとえば、4 行ごとに連結することも簡単です。

array (
  [0] => 1,2,3,4,17,18,19,20,33,34,35,36    // row 1, 5 and 9
  [1] => 5,6,7,8,21,22,23,24                // row 2, 6
  [2] => 9,10,11,12,25,26,27,28             // row 3, 7
)

私は今これを持っています:

$path = "data.csv";
$row = 1;
if (($handle = fopen($path, "r")) !== FALSE) {
  while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
    for ($i = 1; $i <= 3; $i++) { // concatenate every 3rd row
      if ($row % $i == 0) $newrows[$i] .= implode(",", $data);
    }
    $row++;
  }
}

print_r($newrows);

しかし、出力されるため、期待どおりに機能しません

Array (
  [1] => 1,2,3,45,6,7,89,10,11,1213,14,15,1617,18,19,2021,22,23,2425,26,27,2829,30,31,3233,34,35,36
  [2] => 5,6,7,813,14,15,1621,22,23,2429,30,31,32
  [3] => 9,10,11,1221,22,23,2433,34,35,36
)

もっと良いアイデアはありますか?この数学的論理はいつも私を困惑させます! :-)

4

2 に答える 2

4

現在、サーバーにアクセスできないため、テストできませんが、この単純化されたバージョンで動作するはずです。

$path = "data.csv";
$row = 1;

$groupings = 4; // group every n rows

if(($handle = fopen($path, "r")) !== FALSE)
{
    while(($data = fgetcsv($handle, 1000, ",")) !== FALSE)
    {
        $where = $row % $groupings; // which grouping is this?
        $newrows[$where] .= implode(",", $data).",";

        $row++;
    }
}

for($i = 0; $i < count($newrows); $i++)
{
    $newrows[$i] = substr($newrows[$i], 0, -1);
}

追加されるデータがそのグループに追加される最後のデータであるかどうかを検出する方法 (私が考えることができる) がないため、最初の while ループの後に 2 番目のループを実行する必要があります。

于 2012-07-15T10:54:02.793 に答える
3

すべての行を反復処理し、(の場合のようにSplFileObject)ゼロベースの行番号までの余りを新しいインデックスとして計算してからarray、値を入力できます。

次の例では、$perEach配列が入力されます。

$each = 3; # must be greater than 0
$path = '../data/numbers.csv'; # path to the csv file

$file = new SplFileObject($path);
$file->setFlags(SplFileObject::DROP_NEW_LINE);

$perEach = array();
foreach ($file as $lineNumber => $line)
{
    $index = $lineNumber % $each;
    $isNew = empty($perEach[$index]);
    if ($isNew) {
        $perEach[$index] = $line;
    } else {
        $perEach[$index] .= ',' . $line;
    }
}

提供したデータの結果:

array(3) {
  [0] => string(55) ""1","2","3","4","13","14","15","16","25","26","27","28""
  [1] => string(55) ""5","6","7","8","17","18","19","20","29","30","31","32""
  [2] => string(58) ""9","10","11","12","21","22","23","24","33","34","35","36""
}

データ形式がそれほど一貫しておらず、真のCSV解析が必要な場合は、SplFileObjectそれも実行できます。最初に配列を初期化できるので、おそらくさらに良いでしょう:

$file = new SplFileObject($path);
$file->setFlags(SplFileObject::READ_CSV);

$perEach = array_fill(0, $each, array());
foreach ($file as $lineNumber => $line)
{
    $index = $lineNumber % $each;
    $perEach[$index] = array_merge($perEach[$index], $line);
}

その結果、当然、各行の値を離しておくための配列になります。

array(3) {
  [0]=>
  array(12) {
    [0]=>
    string(1) "1"
    [1]=>
    string(1) "2"
    [2]=>
    string(1) "3"
    [3]=>
    string(1) "4"
    [4]=>
    string(2) "13"
    [5]=>
    string(2) "14"
    [6]=>
    string(2) "15"
    [7]=>
    string(2) "16"
    [8]=>
    string(2) "25"
    [9]=>
    string(2) "26"
    [10]=>
    string(2) "27"
    [11]=>
    string(2) "28"
  }
  [1]=>
  array(12) {
    [0]=>
    string(1) "5"
    [1]=>
    string(1) "6"
    [2]=>
    string(1) "7"
    [3]=>
    string(1) "8"
    [4]=>
    string(2) "17"
    [5]=>
    string(2) "18"
    [6]=>
    string(2) "19"
    [7]=>
    string(2) "20"
    [8]=>
    string(2) "29"
    [9]=>
    string(2) "30"
    [10]=>
    string(2) "31"
    [11]=>
    string(2) "32"
  }
  [2]=>
  array(12) {
    [0]=>
    string(1) "9"
    [1]=>
    string(2) "10"
    [2]=>
    string(2) "11"
    [3]=>
    string(2) "12"
    [4]=>
    string(2) "21"
    [5]=>
    string(2) "22"
    [6]=>
    string(2) "23"
    [7]=>
    string(2) "24"
    [8]=>
    string(2) "33"
    [9]=>
    string(2) "34"
    [10]=>
    string(2) "35"
    [11]=>
    string(2) "36"
  }
}
于 2012-07-15T11:31:40.403 に答える