0

I'd like to take an array with this structure:

array
  'Alabama' => 
    array
      0 => 
        array
          'id' => string '11' (length=2)
          'region_name' => string 'Alabama' (length=7)
          'city' => string 'Birmingham' (length=10)
      1 => 
        array
          'id' => string '12' (length=2)
          'region_name' => string 'Alabama' (length=7)
          'city' => string 'Huntsville' (length=10)
      2 => 
        array
          'id' => string '13' (length=2)
          'region_name' => string 'Alabama' (length=7)
          'city' => string 'Mobile' (length=6)
      3 => 
        array
          'id' => string '14' (length=2)
          'region_name' => string 'Alabama' (length=7)
          'city' => string 'Montgomery' (length=10)
  'Alaska' => 
    array
      0 => 
        array
          'id' => string '15' (length=2)
          'region_name' => string 'Alaska' (length=6)
          'city' => string 'Anchorage' (length=9)

And create unordered lists in html, like so:

<ul id="A">
    <li class="state">Alabama</li> 
    <li>Birmingham</li>
    <li>Huntsville</li>
    <li>Mobile</li>
    <li>Montgomery</li>
    <li class="state">Alaska</li>
    <li>Anchorage</li>
</ul> 
<ul id="C">
    <li class="state">California</li>
    <li>Bakersfield</li>
    <li>Fresno</li>
    <li>Los Angeles</li>
</ul>
<ul id="D">
    <li class="state">DC</li>
    <li>Washington</li>
</ul>

The idea is an alphabetically ordered and grouped series of unordered lists, which I can show and hide easily using javascript. That part is easy... This part, I'm lost.

I've tried a sort of nested foreach loop, but the framework I'm using refused to do it citing OutputEscaper errors, which I believe made sense - I really am not sure how to do this properly.

I'd appreciate any help!

edit: Here's how the array is initially formatted:

$this->cityGroups = array();
foreach($this->USCities as $city)
{
  $this->cityGroups[$city['region_name']][] = $city;
}
6
  • So you want both the states and the cities alphabetically sorted? Commented Sep 5, 2011 at 2:18
  • It might be easier if the array was formatted like: array('State 1' => array('City 1', 'City 2', 'City 3'), 'State 2'=>array('City 1', 'City 2', 'City 3')); Commented Sep 5, 2011 at 2:20
  • @PhpMyCoder Would it be possible for me to reformat my array? I've added how it's created to my original post... Maybe formatting that better to begin with would be helpful. Commented Sep 5, 2011 at 2:24
  • It would be easier to work with if you removed the other bloat and just had states as keys and arrays of cities as their values. Commented Sep 5, 2011 at 2:26
  • You know, if this list will never change, it might behoove you to create it beforehand instead making PHP create the list each time it needs to be shown. Commented Sep 5, 2011 at 2:29

2 Answers 2

2

This is simple and it doesn't need a framework. If you data was formatted as I mentioned in my comment...

$data = array('Alabama' => array('Birmingham', 'Huntsville', 'Mobile', 'Montgomery'),
              'Alaska' => array('Anchorage'));
ksort($data);
$formatted = array();
foreach($data as $state => $cities) {
    $formatted[$state{0}][$state] = $cities;
}

foreach($formatted as $letter => $states) {
    echo '<ul id="'.$letter.'">';
    foreach($states as $state => $cities) {
        sort($cities);
        echo '<li class="state">'.$state.'</li>'
        foreach($cities as $city) {
            echo '<li>'.$city.'</li>';
        }
    }
    echo '</ul>';
}
Sign up to request clarification or add additional context in comments.

Comments

1

This solution should achieve what you're looking for:

$lastLetter = "A";
print( '<ul id="A">' );
foreach( $myArray as $key => $array ){
    if( strtoupper( substr( $key, 0, 1 ) ) != $lastLetter ){
        print( '</ul>' );
        $lastLetter = strtoupper( substr( $key, 0, 1 ) );
        print( '<ul id="' . $lastLetter . '">' );
    }
    print( '<li class="state">' . $key . '</li>' );
    foreach( $array as $subArr ){
        print( '<li>' . $subArr['city'] . '</li>' );
    }
}
print( '</ul>' );

If you need an explanation on any specific part, please let me know.

Alternate Solution, in the event your starting letter is variable (may or may not be A)

Change:

$lastLetter = "A";
print( '<ul id="A">' );

to:

$temp = array_keys( $myArray );
$lastLetter = strtoupper( substr( $temp[0], 0, 1 ) );
print( '<ul id="' . $lastLetter . '">' );

5 Comments

This assumes that there is an element that starts with A. What if there wasn't?
This solution is based on the context of the question. The original question provided input based on state and region, in which the assumption is that at least one state will always begin with the Letter A. I will edit my solution to include a case where this is not true.
Although I think it's pretty safe to assume that there will always be a US state beginning with the letter A. That's unless we have another civil war and Alabama succeeds. We'll still have Alaska and Arizona though!
I thought that was a safe bet too, but you never know!
I've added a check for the first letter to this solution. Works perfectly! This is exactly what I needed really - I hate having people 'do my homework' perse, but I'm not very experienced with outputting data from arrays. Seeing this solution has taught me quite a bit. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.