90

私は次の配列を持っています

Array
(
    [0] => Array
        (
            [id] => 96
            [shipping_no] => 212755-1
            [part_no] => reterty
            [description] => tyrfyt
            [packaging_type] => PC
        )

    [1] => Array
        (
            [id] => 96
            [shipping_no] => 212755-1
            [part_no] => dftgtryh
            [description] => dfhgfyh
            [packaging_type] => PC
        )

    [2] => Array
        (
            [id] => 97
            [shipping_no] => 212755-2
            [part_no] => ZeoDark
            [description] => s%c%s%c%s
            [packaging_type] => PC
        )

)

配列をグループ化するにはどうすればよいidですか?これを行うために利用できるネイティブのphp関数はありますか?

このアプローチは機能しますが、を使用してこれを実行したいと思いますforeach。上記では、重複するアイテムを取得するため、回避しようとしていますか?

上記の例idでは2つのアイテムがあるため、内部にある必要がありますid

4

18 に答える 18

194

ネイティブのものはありません。ループを使用するだけです。

$result = array();
foreach ($data as $element) {
    $result[$element['id']][] = $element;
}
于 2012-10-03T10:20:11.070 に答える
42

次のことを試すことができます。

$group = array();

foreach ( $array as $value ) {
    $group[$value['id']][] = $value;
}

var_dump($group);

出力:

array
  96 => 
    array
      0 => 
        array
          'id' => int 96
          'shipping_no' => string '212755-1' (length=8)
          'part_no' => string 'reterty' (length=7)
          'description' => string 'tyrfyt' (length=6)
          'packaging_type' => string 'PC' (length=2)
      1 => 
        array
          'id' => int 96
          'shipping_no' => string '212755-1' (length=8)
          'part_no' => string 'dftgtryh' (length=8)
          'description' => string 'dfhgfyh' (length=7)
          'packaging_type' => string 'PC' (length=2)
  97 => 
    array
      0 => 
        array
          'id' => int 97
          'shipping_no' => string '212755-2' (length=8)
          'part_no' => string 'ZeoDark' (length=7)
          'description' => string 's%c%s%c%s' (length=9)
          'packaging_type' => string 'PC' (length=2)
于 2012-10-03T10:19:59.220 に答える
35

より関数的なプログラミング スタイルでは、次のように使用できます。array_reduce

$groupedById = array_reduce($data, function (array $accumulator, array $element) {
  $accumulator[$element['id']][] = $element;

  return $accumulator;
}, []);
于 2017-06-14T10:12:07.050 に答える
19

.NET LINQ に触発されて、これをまとめました

<?php

// callable type hint may be "closure" type hint instead, depending on php version
function array_group_by(array $arr, callable $key_selector) {
  $result = array();
  foreach ($arr as $i) {
    $key = call_user_func($key_selector, $i);
    $result[$key][] = $i;
  }  
  return $result;
}

 $data = array(
        array(1, "Andy", "PHP"),
        array(1, "Andy", "C#"),
        array(2, "Josh", "C#"),
        array(2, "Josh", "ASP"),
        array(1, "Andy", "SQL"),
        array(3, "Steve", "SQL"),
    );

$grouped = array_group_by($data, function($i){  return $i[0]; });

var_dump($grouped);

?>

そして出来上がり

array(3) {
  [1]=>
  array(3) {
    [0]=>
    array(3) {
      [0]=>
      int(1)
      [1]=>
      string(4) "Andy"
      [2]=>
      string(3) "PHP"
    }
    [1]=>
    array(3) {
      [0]=>
      int(1)
      [1]=>
      string(4) "Andy"
      [2]=>
      string(2) "C#"
    }
    [2]=>
    array(3) {
      [0]=>
      int(1)
      [1]=>
      string(4) "Andy"
      [2]=>
      string(3) "SQL"
    }
  }
  [2]=>
  array(2) {
    [0]=>
    array(3) {
      [0]=>
      int(2)
      [1]=>
      string(4) "Josh"
      [2]=>
      string(2) "C#"
    }
    [1]=>
    array(3) {
      [0]=>
      int(2)
      [1]=>
      string(4) "Josh"
      [2]=>
      string(3) "ASP"
    }
  }
  [3]=>
  array(1) {
    [0]=>
    array(3) {
      [0]=>
      int(3)
      [1]=>
      string(5) "Steve"
      [2]=>
      string(3) "SQL"
    }
  }
}
于 2013-03-14T17:29:47.343 に答える
8

グループ化する列の値を使用してキャッシュし、結果で作成したグループの新しいサブ配列として残りのデータをプッシュします。

function array_group(array $data, $by_column)
{
    $result = [];
    foreach ($data as $item) {
        $column = $item[$by_column];
        unset($item[$by_column]);
        $result[$column][] = $item;
    }
    return $result;
}
于 2016-08-29T13:58:53.237 に答える
5

完全なテスト スイートを備えた Composer の代替案が必要な場合は、array_group_by関数で目的を達成できます。完全な開示:私は上記のライブラリの作成者です。

$grouped = array_group_by($arr, 'id');

また、マルチレベルのグループ化、またはカスタム コールバック関数を使用した複雑なグループ化もサポートしています。

// Multilevel grouping
$grouped = array_group_by($arr, 'id', 'part_no');

// Grouping by a callback/callable function
$grouped = array_group_by($records, function ($row) {
    return $row->city;
});
于 2015-08-30T06:15:22.420 に答える
2
$arr = array();

foreach($old_arr as $key => $item)
{
   $arr[$item['id']][$key] = $item;
}

ksort($arr, SORT_NUMERIC);
于 2012-10-03T10:16:50.153 に答える
2
for($i = 0 ; $i < count($arr)  ; $i++ )
{
    $tmpArr[$arr[$i]['id']] = $arr[$i]['id'];
}
$vmpArr = array_keys($tmpArr);
print_r($vmpArr);
于 2012-10-03T10:23:07.337 に答える
2

1. GROUP BY1 つのキー

この関数GROUP BYは配列と同様に機能しますが、重要な制限が 1 つあります。グループ化できる「列」は 1 つだけです ( $identifier)。

function arrayUniqueByIdentifier(array $array, string $identifier)
{
    $ids = array_column($array, $identifier);
    $ids = array_unique($ids);
    $array = array_filter($array,
        function ($key, $value) use($ids) {
            return in_array($value, array_keys($ids));
        }, ARRAY_FILTER_USE_BOTH);
    return $array;
}

2. テーブル (2 次元配列) の一意の行の検出

この関数は、「行」をフィルタリングするためのものです。2 次元配列がテーブルであるとすれば、その各要素は行です。したがって、この関数を使用して重複した行を削除できます。すべての列 (2 番目の次元の要素) が等しい場合、2 つの行 (1 番目の次元の要素) は等しいと見なされます。「列」値の比較に適用されます。値が単純の場合、値自体が比較に使用されます。それ以外の場合は、そのタイプ ( arrayobjectresourceunknown type) が使用されます。

戦略は簡単です。元の配列から、要素がimplode元の配列の「列」である浅い配列を作成します。それを適用array_unique(...)します。最後に、検出された ID を元の配列のフィルタリングに使用します。

function arrayUniqueByRow(array $table = [], string $implodeSeparator)
{
    $elementStrings = [];
    foreach ($table as $row) {
        // To avoid notices like "Array to string conversion".
        $elementPreparedForImplode = array_map(
            function ($field) {
                $valueType = gettype($field);
                $simpleTypes = ['boolean', 'integer', 'double', 'float', 'string', 'NULL'];
                $field = in_array($valueType, $simpleTypes) ? $field : $valueType;
                return $field;
            }, $row
        );
        $elementStrings[] = implode($implodeSeparator, $elementPreparedForImplode);
    }
    $elementStringsUnique = array_unique($elementStrings);
    $table = array_intersect_key($table, $elementStringsUnique);
    return $table;
}

タイプが の場合、「列」値のクラスを検出して比較を改善することもできますobject

$implodeSeparator多かれ少なかれ複雑な zB である必要がありますspl_object_hash($this)


3. テーブル(二次元配列)の一意識別子列を持つ行を検出する

このソリューションは、2 番目のソリューションに依存しています。完全な「行」が一意である必要はありません。1 つの「行」の関連するすべての「フィールド」(2 番目の次元の要素) が対応する「フィールド」(同じキーを持つ要素) と等しい場合、2 つの「行」(最初の次元の要素) は等しくなります。

「関連する」「フィールド」は、渡された「識別子」の要素の 1 つに等しいキーを持つ「フィールド」(2 番目の次元の要素) です。

function arrayUniqueByMultipleIdentifiers(array $table, array $identifiers, string $implodeSeparator = null)
{
    $arrayForMakingUniqueByRow = $removeArrayColumns($table, $identifiers, true);
    $arrayUniqueByRow = $arrayUniqueByRow($arrayForMakingUniqueByRow, $implodeSeparator);
    $arrayUniqueByMultipleIdentifiers = array_intersect_key($table, $arrayUniqueByRow);
    return $arrayUniqueByMultipleIdentifiers;
}

function removeArrayColumns(array $table, array $columnNames, bool $isWhitelist = false)
{
    foreach ($table as $rowKey => $row) {
        if (is_array($row)) {
            if ($isWhitelist) {
                foreach ($row as $fieldName => $fieldValue) {
                    if (!in_array($fieldName, $columnNames)) {
                        unset($table[$rowKey][$fieldName]);
                    }
                }
            } else {
                foreach ($row as $fieldName => $fieldValue) {
                    if (in_array($fieldName, $columnNames)) {
                        unset($table[$rowKey][$fieldName]);
                    }
                }
            }
        }
    }
    return $table;
}
于 2016-05-23T14:00:57.980 に答える
2

YaLinqo * . 配列とオブジェクトに対して SQL のようなクエリを実行できます。このgroubBy関数は、グループ化のために特別に設計されています。グループ化するフィールドを指定するだけです。

$grouped_array = from($array)->groupBy('$v["id"]')->toArray();

Whereは、このライブラリがサポート'$v["id"]'する省略形です。function ($v) { return $v["id"]; }

結果は、コードが少ないだけで、受け入れられた回答とまったく同じになります。

※私が開発した

于 2015-06-04T15:58:12.890 に答える
2

私が好きな@babaの答えを拡張しますが、より複雑な3レベルの深さの多次元(配列(配列(配列)))を作成します:

$group = array();
 foreach ( $array as $value ) {
   $group[$value['id']][] = $value; 
 }

// output only data from id 96
foreach ($group as $key=>$value) { //outer loop
 foreach ($value as $k=>$v){ //inner loop
  if($key==96){ //if outer loop is equal to 96 (could be variable)
   for ($i=0;$i<count($k);$i++){ //iterate over the inner loop
        printf($key.' has a part no. of '.$v['part_no'].' and shipping no. of '.$v['shipping_no'].'<br>');
   }
 }
}
 }

出力します:

96には品番があります。212755-1のリターティと出荷番号

96には品番があります。dftgtryh と出荷番号 212755-1 の

于 2012-10-03T12:13:49.990 に答える
1

これは連想配列をグループ化する必要があります Ejm Group By Country

function getGroupedArray($array, $keyFieldsToGroup) {   
    $newArray = array();

    foreach ($array as $record) 
        $newArray = getRecursiveArray($record, $keyFieldsToGroup, $newArray);

    return $newArray;
}
function getRecursiveArray($itemArray, $keys, $newArray) {
    if (count($keys) > 1) 
        $newArray[$itemArray[$keys[0]]] = getRecursiveArray($itemArray,    array_splice($keys, 1), $newArray[$itemArray[$keys[0]]]);
    else
        $newArray[$itemArray[$keys[0]]][] = $itemArray;

    return $newArray;
}

$countries = array(array('Country'=>'USA', 'State'=>'California'),
                   array('Country'=>'USA', 'State'=>'Alabama'),
                   array('Country'=>'BRA', 'State'=>'Sao Paulo'));

$grouped = getGroupedArray($countries, array('Country'));
于 2015-09-08T17:48:05.063 に答える