Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Short project description: I need to output specific values from an existing array for a tabbed alphabetical navigation. The navigation groups several letters together into tabs (i.e. 'A-C') and then displays all links to posts starting with those letters. The navigation is created by a plugin, so I need to create variables to output the groups.

What I have: I have an array which is sorted in alphabetical order by the name key of the child array. It looks like the following example:

Array (
  [0] => Array ( 
    ['name'] => 'Alpha'
    ['link'] => 'http://www.someurl.com' 
  )    

  [1] => Array ( 
    ['name'] => 'Alpha2'
    ['link'] => 'http://www.someotherurl.com' 
  )     

  [2] => Array ( 
    ['name'] => 'Beta'
    ['link'] => 'http://www.someurl.com' 
  )

  [3] => Array ( 
    ['name'] => 'Delta'
    ['link'] => 'http://www.someotherurl.com' 
  )

  [4] => Array ( 
    ['name'] => 'Zephyr'
    ['link'] => 'http://www.someurl.com' 
  )
)

What I think needs to happen: I need to create 5 new arrays that group these child arrays alphabetically. Meaning, I need to get all arrays whose name starts with 'A' - 'C' into one array, 'D' - 'G' into another, etc.

In other words, the array shown above would result in the follow being created:

$a_c = array(
  [0] => Array ( 
    ['name'] => 'Alpha'
    ['link'] => 'http://www.someurl.com' 
  )    
  [1] => Array ( 
    ['name'] => 'Alpha2'
    ['link'] => 'http://www.someotherurl.com' 
  )     
  [2] => Array ( 
    ['name'] => 'Beta'
    ['link'] => 'http://www.someurl.com' 
  )   
);

$d_g = array(
  [0] => Array ( 
    ['name'] => 'Delta'
    ['link'] => 'http://www.someotherurl.com' 
  )
);
$h_l = array();
$m_r = array();
$s_t = array();
$u_z = array(
  [0] => Array ( 
    ['name'] => 'Zephyr'
    ['link'] => 'http://www.someurl.com' 
  )
);

If a new array value such as [5] => Array (['name'] => 'Kappa' ['link'] => 'http://www.someurl.com') gets added to the first array, it will be added to the array in the $h_l variable.

Does anyone know how or if this can be done?

share|improve this question
1  
What you tried so far? –  Alma Do 23 hours ago
 
@almo do: I haven't tried much...I honestly have no idea what to try or even what to look for to help me figure it out. I have seen things on dividing an array into separate letters (meaning a nav structure like 'A' 'B' 'C' rather than 'A-C') but nothing like the one I need. Any thoughts about what I could look at? –  IamSparticus 23 hours ago
add comment

4 Answers

up vote 1 down vote accepted

Here is one method using a final output array rather than many different range arrays.

Loop through your original array, determine into which predefined range the first letter falls, add the current entry to the appropriate range of the final output array.

// define ranges
$ranges=array(
    'A-C'=>range('A','C'),
    'D-G'=>range('D','G'),
    'H-K'=>range('H','K'),
    'L-O'=>range('L','O'),
    'P-S'=>range('P','S'),
    'T-W'=>range('T','W'),
    'X-Z'=>range('X','Z')
);

// build final array with each entry in its appropriate range
$final=array();
foreach ($data as $item) {
    $first_letter=strtoupper(substr($item['name'],0,1));
    foreach ($ranges as $label => $range) {
        if (in_array($first_letter,$range)) {
            $final[$label][]=$item;
            break;
        }
    }
}

// output the final array
echo"<pre>".print_r($final,true)."</pre>";

Here is the output:

Array
(
    [A-C] => Array
        (
            [0] => Array
                (
                    [name] => Alpha
                    [link] => http://www.someurl.com
                )

            [1] => Array
                (
                    [name] => Alpha2
                    [link] => http://www.someotherurl.com
                )

            [2] => Array
                (
                    [name] => Beta
                    [link] => http://www.someurl.com
                )

        )

    [D-G] => Array
        (
            [0] => Array
                (
                    [name] => Delta
                    [link] => http://www.someotherurl.com
                )

        )

    [X-Z] => Array
        (
            [0] => Array
                (
                    [name] => Zephyr
                    [link] => http://www.someurl.com
                )

        )

)

http://phpfiddle.org/main/code/w06-sc5

share|improve this answer
add comment

If the criteria to determine which values go into which array is just the name, is there any reason why you can't just loop through the main array with foreach() and pattern match the first character? Alternatively, you could use substr() to save the first character to a variable, and then match against this in a switch() test. If it was purely a one-to-one arrangement (ie you had a different array for each letter of the alphabet) then you could use a dynamically named variable to make the association.

share|improve this answer
add comment

Ok, I write the idea I had. Using $$ I'll access to a variable name that is parametric. The value (example $a_c, $d_f, ecc...) is generated starting with the informations I had based on the actual "name" parameter.

The variable name is:

I get the starting letter of the actual ["name"] value (with substr). With ord() I get the corrisponding value in ascii.

Dividing / 3 and multiplying by 3, I obtain the first letter of the "group of letters" in which it belongs (example: if the first letter is "B", I'll get the "a" of "a_c").

This value + 2 is the final letter.

I append those two informations, turning back to a string with chr().

I didn't tested at all, here's an example pseudo-code:

foreach ($myarray as $value)
{
    //finding the name of the variable. the variable name is derived by the letter of the actual value["name"]. the last letter is the first + 2. the name is divided by an underscore.
    $first_letter = intval((substr(ord($value["name"], 0, 1)) - ord('A')) / 3)*3 + ord('A');
    $last_letter = $first_letter + 2;
    $var_name = chr($first_letter)."_".chr($first_letter);
    if (!isset($$var_name))
        $$var_name = array();
    $$var_name[] = $value;
}
share|improve this answer
add comment

Try this function . This function consist of two parameters, one is the letter you wish to search and the other is the source array.

function getNewArray($letter='A',$arr){
  if(!is_array($arr)) return;
  $result=array();
  foreach($arr as $a){
    if( strtolower(trim($a['name'][0])) === strtolower($letter)){
            $result[] = $a; 
    }
  }
  return $result;
}

//This function returns an array with name starting with letter m. first argument is NOT case sensitive getNewArray('M',$array); // here $array is your source array.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.