按字母范围对数组元素进行分组 [英] Group Array Elements by Letter Range
问题描述
我有一个简单的数组,里面有一些名称,我想按它们的首字母分组。
例如所有以A到C作为第一个字母的名称都将排入一个数组,将D到F的名称都移到另一个,以此类推。
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?
推荐答案
我现在有四种方法可以提供。可以通过更改 $ size
将所有内容修改为允许更大或更小的组。
I now have four methods to offer. All can be modified to allow for larger or smaller groups by changing $size
.
- 2创建 AB, CD等。
- 3创建 ABC, DEF等。
- 4创建 ABCD, EFGH等。
- 15创建 ABCDEFGHIJKLMNO, PQRSTUVWXYZ
- 2 creates "AB","CD",etc.
- 3 creates "ABC","DEF",etc.
- 4 creates "ABCD","EFGH",etc.
- 15 creates "ABCDEFGHIJKLMNO","PQRSTUVWXYZ"
代码#1 通过使用2个 foreach()
循环并对每个值的第一个字符进行比较,将值作为数组处理。这是最容易理解的。
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);
代码#2 集成了apokryfos非常聪明的 ord()
与Code#1行,以消除内部循环(和内部循环本身)的不匹配迭代。这样可以提高效率,但会对可读性产生负面影响。
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);
代码#3 通过使用<$将值作为csv字符串处理c $ c> preg_match_all()和一些过滤功能。假设没有值包含逗号。我认为,由于所有功能和非常长的正则表达式模式,很难一眼就理解该代码。
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);
}
代码#4 将值作为数组处理通过使用以下方式而没有循环或条件: array_map()
, preg_grep()
, array_values()
, array_combine()
和 array_filter
形成单线*折扣 $ size
& $ chunks
声明。 ...我不愿意停下脚步,直到制造出单层纸面-无论多么难看。 ;)
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',
),
)
这篇关于按字母范围对数组元素进行分组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!