dongsui0929 2017-04-12 13:50
浏览 73
已采纳

按字母范围分组数组元素

I have a simple array with some names in it and I want to group them by their first letter. E.g. all names with A to C as first letter go in an array and D to F go to another one and so on.

Is there a better way to do it than using lots of if else?

  • 写回答

3条回答 默认 最新

  • douzhong3887 2017-04-12 14:19
    关注

    I now have four methods to offer. All can be modified to allow for larger or smaller groups by changing $size.

    • 2 creates "AB","CD",etc.
    • 3 creates "ABC","DEF",etc.
    • 4 creates "ABCD","EFGH",etc.
    • 15 creates "ABCDEFGHIJKLMNO","PQRSTUVWXYZ"

    Code#1 processes the values as an array by using 2 foreach() loops and a comparison on the first character of each value. This is the easiest to comprehend.

    $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);
    

    Code#2 integrates apokryfos' very clever ord() line with Code#1 to eliminate the non-matching iterations of the inner loop (and the inner loop itself). This delivers improvement on efficiency, but a negative impact on readability.

    $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);
    

    Code#3 processes the values as a csv string by using preg_match_all() and some filtering functions. This assumes that no values include commas in them. In my opinion, this code is hard to comprehend at a glance because of all of the functions and the very long regex pattern.

    $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);
    }
    

    Code#4 processes the values as an array without loops or conditionals by using: array_map(), preg_grep(), array_values(), array_combine(), and array_filter to form a one-liner *discounting the $size & $chunks declarations. ...I don't like to stop until I've produced a one-liner -- no matter how ugly. ;)

    $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)
    //            )
    //        );
    

    All codes output an identical result:

    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',
      ),
    )
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 GD32 SPI通信时我从机原样返回收到的数据怎么弄?
  • ¥15 phython读取excel表格报错 ^7个 SyntaxError: invalid syntax 语句报错
  • ¥20 @microsoft/fetch-event-source 流式响应问题
  • ¥15 ogg dd trandata 报错
  • ¥15 高缺失率数据如何选择填充方式
  • ¥50 potsgresql15备份问题
  • ¥15 Mac系统vs code使用phpstudy如何配置debug来调试php
  • ¥15 目前主流的音乐软件,像网易云音乐,QQ音乐他们的前端和后台部分是用的什么技术实现的?求解!
  • ¥60 pb数据库修改与连接
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?