2017-04-12 14 views
2

いくつかの名前を持つ単純な配列があり、最初の文字でグループ化したいと思います。 など。最初の文字としてAからCまでのすべての名前は配列に入れられ、DからFへの名前は別の文字に移動します。レターレンジ別グループ配列要素

if elseをたくさん使うよりも良い方法がありますか?

+0

あなたの単純な配列はどこですか?あなたの質問 –

+1

でそれを更新してください。これはバケットに分割されている「ソート」ではありません。各バケットのサイズが1になるまで再帰的に実行し、バケットをマージすると、基数ソートが行われます。 – apokryfos

+0

なぜこの並べ替えを使用するのが通常の並べ替えですか? – Zac

答えて

1

私は現在4つの方法を提供しています。 $sizeを変更することで、すべてのグループを拡大または縮小することができます。

  • 2 "AB"、 "CD"などを作成します。
  • 3 "ABC"、 "DEF"などを作成します。
  • 4 "ABCD"、 "EFGH"などを作成します。
  • 15は、コード#1 2つのforeach()ループを用いてアレイ及び各値の最初の文字に比較として値を処理

「ABCDEFGHIJKLMNO」、「PQRSTUVWXYZ」を作成します。これは理解するのが一番簡単です。

$fruits=array("date","guava","lemon","Orange","kiwi","Banana","apple"); 
natcasesort($fruits); // pre-sort them for alphabetized output 
$size=3; // <-modify group sizes here 
$chunks=array_chunk(range('A','Z'),$size); // 0=>["A","B","C"],1=>["D","E","F"],etc... 
foreach($fruits as $fruit){ 
    foreach($chunks as $letters){ 
     if(in_array(strtoupper($fruit[0]),$letters)){ // check if captialized first letter exists in $letters array 
      $groups[implode($letters)][]=$fruit; // push value into this group 
      break; // go to next fruit/value 
     } 
    } 
} 
var_export($groups); 

コード#2は、内側ループ(及びインナーループ自体)の非マッチングの繰り返しを排除するためにコード#1 apokryfos'非常に巧妙なord()ラインを統合します。これは効率の向上をもたらしますが、可読性に悪影響を与えます。

$fruits=array("date","guava","lemon","Orange","kiwi","Banana","apple"); 
natcasesort($fruits); // pre-sort them for alphabetized output 
$size=3; // <-modify group sizes here 
$chunks=array_chunk(range('A','Z'),$size); // 0=>["A","B","C"],1=>["D","E","F"],etc... 
foreach($fruits as $fruit){ 
    $groups[implode($chunks[floor((ord(strtoupper($fruit[0]))-ord("A"))/$size)])][]=$fruit; 
} 
var_export($groups); 

コード#3プロセスpreg_match_all()を使用してCSV文字列として値と、いくつかのフィルタリング機能。これは、カンマが値に含まれていないことを前提としています。私の意見では、このコードは、すべての関数と非常に長い正規表現パターンのため、一見して理解するのは難しいです。

$fruits=array("date","guava","lemon","Orange","kiwi","Banana","apple"); 
natcasesort($fruits); // pre-sort them for alphabetized output // array(6 => 'apple',5 => 'Banana',0 => 'date',1 => 'guava',4 => 'kiwi',2 => 'lemon',3 => 'Orange') 
$size=3; // <-modify group sizes here 
$chunks=str_split(implode(range('A','Z')),$size); // ['ABC','DEF','GHI','JKL','MNO','PQR','STU','VWX','YZ'] 
$regex="/((?<=^|,)[".implode('][^,]*)|((?<=^|,)[',$chunks)."][^,]*)/i"; // '/((?<=^|,)[ABC][^,]*)|((?<=^|,)[DEF][^,]*)|((?<=^|,)[GHI][^,]*)|((?<=^|,)[JKL][^,]*)|((?<=^|,)[MNO][^,]*)|((?<=^|,)[PQR][^,]*)|((?<=^|,)[STU][^,]*)|((?<=^|,)[VWX][^,]*)|((?<=^|,)[YZ][^,]*)/i' 
if(preg_match_all($regex,implode(",",$fruits),$out)){ 
    $groups=array_map('array_values', // 0-index subarray elements 
     array_filter(     // omit empty subarrays 
      array_map('array_filter', // omit empty subarray elements 
       array_combine($chunks, // use $chunks as keys for $out 
        array_slice($out,1) // remove fullstring subarray from $out 
       ) 
      ) 
     ) 
    ); 
    var_export($groups); 
} 

コード#4用いてループまたは条件式無しアレイなどのプロセス値:ワンライナーを形成するarray_map()を、preg_grep()array_values()array_combine()、及びarray_filter * $size & $chunks宣言を割り引きます。 ...私は1ライナーを作るまで停止したくない - どんなに醜い。 ;)

$fruits=array("date","guava","lemon","Orange","kiwi","Banana","apple"); 
natcasesort($fruits); // pre-sort them for alphabetized output 
$size=3; // <-modify group sizes here 
$chunks=str_split(implode(range('A','Z')),$size); // ['ABC','DEF','GHI','JKL','MNO','PQR','STU','VWX','YZ'] 
$groups=array_filter(array_combine($chunks,array_map(function($v)use($fruits){return array_values(preg_grep("/^[$v].*/i",$fruits));},$chunks))); 
var_export($groups); 


// $groups=array_filter( // remove keys with empty subarrays 
//   array_combine($chunks, // use $chunks as keys and subarrays as values 
//    array_map(function($v)use($fruits){ // check every chunk 
//     return array_values( // reset subarray's keys 
//      preg_grep("/^[$v].*/i",$fruits) // create subarray of matches 
//     ); 
//    },$chunks) 
//   ) 
//  ); 

すべてのコード出力と同じ結果:あなたはこれを行うことができ

array (
    'ABC' => 
    array (
    0 => 'apple', 
    1 => 'Banana', 
), 
    'DEF' => 
    array (
    0 => 'date', 
), 
    'GHI' => 
    array (
    0 => 'guava', 
), 
    'JKL' => 
    array (
    0 => 'kiwi', 
    1 => 'lemon', 
), 
    'MNO' => 
    array (
    0 => 'Orange', 
), 
) 
1

function buckets($array, callable $bucketFunc) { 
    $buckets = []; 

    foreach ($array as $val) { 
     $bucket = $bucketFunc($val); 
     if (!isset($buckets[$bucket])) { 
      $buckets[$bucket] = []; 
     } 
     $buckets[$bucket][] = $val; 
    } 
    return $buckets; 
} 

function myBucketFunc($value) { 
     //Gets the index of the first character and returns which triple of characters it belongs to 
     return floor((ord(ucfirst($value)) - ord("A"))/3); 
} 
$array = [ "Abc", "Cba", "Foo","Hi", "Bar" ]; 

$buckets = buckets($array, 'myBucketFunc');//Any function would 

返します:

Array 
(
    [0] => Array 
     (
      [0] => Abc 
      [1] => Cba 
      [2] => Bar 
     ) 

    [1] => Array 
     (
      [0] => Foo 
     ) 

    [2] => Array 
     (
      [0] => Hi 
     ) 

) 

さらに明確化:

ordは、文字のASCII値を返します。

Doing ord("X") - ord("A")は、Xの文字インデックスを返します。

アルファベットを3文字ずつバケットに分割すると、その文字インデックスを3で割るとXのバケット番号が返されます。

+0

私はインスピレーションを得た 'ord()'行が役立つことから、この回答をアップフォームしています。 – mickmackusa

0

これは、非スカラ方式でarray_reduceの良い使用です:

function keyize(string $word, $stride = 3): string { 
    $first = strtoupper($word{0}); 
    $index = (int)floor((ord($first) - ord('A'))/$stride); 
    return implode('', array_chunk(range('A', 'Z'), $stride)[$index]); 
} 

function bucketize(array $words, $stride = 3): array { 
    return array_reduce(
     $words, 
     function ($index, $word) use ($stride) { 
      $index[keyize($word, $stride)][] = $word; 
      return $index; 
     }, 
     [] 
    ); 
} 

$words = [ 'alpha', 'Apple', 'Bravo', 'banana', 'charlie', 'Cucumber', 'echo', 'Egg', ]; 
shuffle($words); 
$buckets = bucketize($words, 3); // change the number of characters you want grouped, eg 1, 13, 26 
ksort($buckets); 
var_dump($buckets); 

だから私たちは歩いてarray_reduceを使用している - と同時に構築 - バケットを。バケット配列は各クロージャ呼び出しによってコピーされるため、実装するのが最も効率的です。しかし、コンパクトです。

関連する問題