Reputation: 106
I need to render my array into a group like this:
[group]{A} abc alpha apple [/group]
However, it doesn't want to work yet with this code:
sort($array, SORT_NATURAL | SORT_FLAG_CASE);
$batch = '';
$previous = strtoupper(substr($array[0], 0, 1));
foreach($array as $value) {
$firstLetter = strtoupper(substr($value, 0, 1));
if($previous !== $firstLetter){
echo "[group]{" . substr($firstLetter, 0,1) . "}\n" . $batch . "[/group]\n\n";
$batch = NULL;
}
else{
$batch.= $value."\n";
}
$previous = $firstLetter;
}
Example input:
a
a
a
b
b
c
Example Output:
[submenu] (B)
a
a
a
[/group]
[submenu] (C)
b
[/group]
Output after advice from 'ElefantPhace' in the comments:
[submenu] (A)
a
a
a
[end]
[submenu] (A)
[group]
[submenu] (A)
[group]
Keeping the '$previous = $firstLetter;' after the 'else' gives me:
[submenu] (A)
a
a
a
[end]
[submenu] (B)
b
[group]
Which is fine except for the fact that I miss the last item 'c'
NOTE: I left the $previous
in my group.
Upvotes: 0
Views: 683
Reputation: 3814
A working example using your method:
$array = ['alpha','abc','android','braces','barbs','brackets','crabs','cool'];
sort($array, SORT_NATURAL | SORT_FLAG_CASE);
$batch = '';
$previous = strtoupper(substr($array[0], 0, 1));
$count = count($array);
$i=0;
foreach($array as $value) {
$i++;
$firstLetter = strtoupper(substr($value, 0, 1));
if($previous !== $firstLetter || $i == $count){
if($i == $count) $batch.=$value."\n";
echo "[group]{".$previous."}\n" . $batch . "[/group]\n\n";
$batch = $value."\n";
}else{
$batch.= $value."\n";
}
$previous = $firstLetter;
}
Output:
[group]{A} abc alpha android [/group]
[group]{B} barbs braces brackets [/group]
[group]{C} cool crabs[/group]
Not very pretty, but it works!
Upvotes: 0
Reputation: 4913
Working off your code you can make the following changes to get what you want:
$array = array("a", "ac", "ab", "bc", "be", "bd", "ce", "cg", "cf");
sort($array, SORT_NATURAL | SORT_FLAG_CASE);
$batch = '';
$output = '';
$previous = strtoupper(substr($array[0], 0, 1));
foreach($array as $value) {
//Get the first letter
$firstLetter = strtoupper(substr($value, 0, 1));
//Check if in a new group, otherwise add $value to current group
if($previous != $firstLetter) {
//In a new group, so prep for the next group.
$output .= "[group]{" . $previous . "}\n" . $batch . "[/group]\n\n";
$previous = $firstLetter;
$batch = '';
} else {
$batch .= $value."\n";
}
}
//Get the last batch.
$output .= "[group]{" . $previous . "}\n" . $batch . "[/group]\n\n";
print($output);
This will produce:
[group]{A}
a
ab
ac
[/group]
[group]{B}
bd
be
[/group]
[group]{C}
cf
cg
[/group]
Hope that helps you out!
Upvotes: 0
Reputation: 6908
A cleaner way is to avoid the checking if you're using a new letter (the if($previous !== $firstLetter)
stuff), and instead use the first letter as an index in a new array, like so:
sort($array, SORT_NATURAL | SORT_FLAG_CASE);
$treeArray = array();
foreach($array as $el) {
$firstLetter = strtoupper(substr($el, 0, 1));
if(!(isset($treeArray[$firstLetter])) ) { $treeArray[$firstLetter] = array(); }
array_push($treeArray[$firstLetter], $el);
}
Now, you'll have an array which uses each of the first letters as an index, so you can loop through it later to display like:
foreach($treeArray as $letter => $contents) {
echo '[submenu] ' . $letter, PHP_EOL;
foreach($contents as $el) {
echo $el, PHP_EOL;
}
}
Upvotes: 1