0

How to sort an array based on another array in php? I have this list of persons, actually they are 1300 + people... I will only display 22 people here :)

persons array:

Array ( 
    [0] => Array ( [name] => Kay [site] => ex [rate] => 10 ) 
    [1] => Array ( [name] => Kat [site] => ih [rate] => 9.7 )
    [2] => Array ( [name] => Kate [site] => tp [rate] => 9 )
    [3] => Array ( [name] => rina [site] => tc [rate] => 9.8 )
    [4] => Array ( [name] => Katay [site] => cfnm [rate] => 6.8 )
    [5] => Array ( [name] => teriay [site] => sn [rate] => 7.6 )
    [6] => Array ( [name] => Kaay [site] => tla [rate] => 9.7 )
    [7] => Array ( [name] => na Kay [site] => bsc [rate] => 9.5 )
    [8] => Array ( [name] => qwerty [site] => tdp [rate] => 9.5 )
    [9] => Array ( [name] => Katey [site] => hd [rate] => 9.4 )
    [10] => Array ( [name] => Kat Kay [site] => ss [rate] => 9.2 )
    [11] => Array ( [name] => ina Kay [site] => pv [rate] => 9.43 )
    [12] => Array ( [name] => ina [site] => rat [rate] => 9.32 )
    [13] => Array ( [name] => atay [site] => trw [rate] => 9.32 )
    [14] => Array ( [name] => erina [site] => tlm [rate] => 9.43 )
    [15] => Array ( [name] => Ky [site] => ol [rate] => 8.34 )
    [16] => Array ( [name] => ikay [site] => tb [rate] => 7.34 )
    [17] => Array ( [name] => jay [site] => ta [rate] => 6.5 )
    [18] => Array ( [name] => saday [site] => hfy [rate] => 4.6 )
    [19] => Array ( [name] => tarans [site] => sd [rate] => 6.54 )
    [20] => Array ( [name] => dastw [site] => si [rate] => 6.4 )
    [21] => Array ( [name] => dyr say [site] => ex [rate] => 7.6 )
) 

and there is an another array called site which i want to display them accordingly, only one person per site per loop and when the site array reached to the end then it will start to top until the lists of persons are done reading.

by site order array

Array ( [0] => Array ( [acronym] => exs [site_order] => 1 ) 
[1] => Array ( [acronym] => ts [site_order] => 1 ) 
[2] => Array ( [acronym] => ih [site_order] => 2 ) 
[3] => Array ( [acronym] => tp [site_order] => 3 ) 
[4] => Array ( [acronym] => tc [site_order] => 4 ) 
[5] => Array ( [acronym] => cfnm [site_order] => 5 ) 
[6] => Array ( [acronym] => sn [site_order] => 6 ) 
[7] => Array ( [acronym] => tla [site_order] => 7 ) 
[8] => Array ( [acronym] => bsc [site_order] => 8 ) 
[9] => Array ( [acronym] => tdp [site_order] => 9 ) 
[10] => Array ( [acronym] => lhd [site_order] => 10 ) 
[11] => Array ( [acronym] => ss [site_order] => 11 ) 
[12] => Array ( [acronym] => pov [site_order] => 12 ) 
[13] => Array ( [acronym] => rat [site_order] => 13 ) 
[14] => Array ( [acronym] => trw [site_order] => 14 ) 
[15] => Array ( [acronym] => tgs [site_order] => 15 ) 
[16] => Array ( [acronym] => tlm [site_order] => 16 ) 
[17] => Array ( [acronym] => ol [site_order] => 17 ) 
[18] => Array ( [acronym] => tb [site_order] => 18 ) 
[19] => Array ( [acronym] => ta [site_order] => 19 ) 
[20] => Array ( [acronym] => hfy [site_order] => 20 ) 
[21] => Array ( [acronym] => sd [site_order] => 21 ) 
[22] => Array ( [acronym] => si [site_order] => 22 ) 
[23] => Array ( [acronym] => tse [site_order] => 23 ) 
[24] => Array ( [acronym] => ih [site_order] => 24 ) 
)

I also want to display them by rate. but I cant even display a correct data because when the site array foreach is finish then it stop loading on people. this is what my code so far...

$x = 0;
$num = 0;
foreach ($site as $item) {
        foreach ($data as $person)
        {
            if($site[$num]['acronym'] == $persons['site'] && $x != 1)
            {
                echo 'name: '.$person['site'].'<br>';
                echo 'site: '.$person['name'].'<br>';
                echo '<br>';

                $x++;
            }
        }
        $x = 0;
    $num++;
}

what output i want is for example:

site: ex
name: kay
rate: 10

site: tp
name: kate
rate: 9

site: tc
name: rina
rate: 9.8

site: ih
name: kat
rate: 9.7

site: tla
name: Kaay
rate: 9.7
.
.
.
and so on

note that I want a condition that: loop persons order by site orders and order by rate but only one person per site loop.

I know it sounds bit complicated but please help me. i searched so much thread here that has the same problem as me, but no luck. :'(

2
  • 1
    can you add your desired output? Commented Nov 7, 2015 at 8:53
  • yes sure @roullie wait a minute Commented Nov 7, 2015 at 8:54

3 Answers 3

2

The following code is a possible solution:

$already_printed = Array();
$total_of_people = count($people);
// while there is someone that was not printed yet
while(count($already_printed) < $total_of_people){
  // iterate thought each site
  foreach($sites as $site){
      // take each person and its position in the array
      foreach ($people as $i => $person){
          // if this i-th person was not printed yet
          // and is related to this $site
          if (! isset($already_printed[$i])
              && $person['site'] == $site['acronym']){
                // print this person
                echo 'site: '.$person['site'].'<br>';
                echo 'name: '.$person['name'].'<br>';
                echo '<br>';
                // mark this i-th person as printed
                $already_printed[$i] = true;
          }

      }
  }
}

The array already_printed is used to know who was already printed to avoid double printing. When its size is equal to the total of people, then, we printed everybody, so, we can stop (this is what the outer loop does).

Sign up to request clarification or add additional context in comments.

11 Comments

yeah i think so, gonna try this. but i think this code foreach($sites as $site) must be foreach($site as $sites) right?
Hey bud @vitor can you explain me how this works? $person = $people[$i]; is this directly called on the persons=array() above?
im having an error here it says Undefined offset: 1 on the $data = $data[$i];
About the foreach: $sites is the array with all the sites and $site is the variable containing a single site. I think the syntax is right.
Ans, in order to display the people by rate, you just have to sort the array people by the attribute rate before the line while(count($already_printed) < $total_of_people). Doing so, the first person found for each site will be the top rated person, and so on.
|
1

The key is to organize that large array into a format that doesn't force you to iterate through it more times than necessary. Give this a shot:

$highest = array();

foreach ($data as $person) {
    if (!array_key_exists($person['site'], $highest) || ($person['rate'] > $highest[$person['site']]['rate'])) {
        $highest[$person['site']] = $person;
    }
}

foreach ($site as $item) {
    if (array_key_exists($item['acronym'], $highest)) {
        echo "site: {$highest[$item['acronym']]['site']}<br />name:{$highest[$item['acronym']]['name']}<br />rate:{$highest[$item['acronym']]['rate']}";
    }
}

As a side note, good call on changing 'girls' to 'person' so this isn't so obviously an application created to rate women...

3 Comments

but I want to display only one person per site loop. and it must be order by rate asc @rawb
hmmm i have 1300 + persons here but it seems they didnt display all the list. hehe. but i think we're getting there.
It was my understanding that you just wanted the top rated person displayed per-site, but either way this should point you in the right direction! Similar to the approach above -- I'd recommend sorting the people by site first (in a multidimensional array indexed by site), then sorting each of those site sub-arrays by rating, and then looping through the whole thing (while there are still people left) and echoing out what you need. Good luck and happy coding!
1

Using your code I would do something like this:

foreach ($site as $item) {
            $maxRate = 0;
            $savePerson = array();
            foreach ($data as $person)
            {
                if($item['acronym'] == $girls['site'] && $person['site'] == $girls['site'] && $person['rate'] > $maxRate)
                {
                    $maxRate = $person['rate'];
                    $savePerson = $person;
                }
            }
           if(!empty($savePerson)){
                    echo 'name: '.$savePerson['site'].'<br>';
                    echo 'site: '.$savePerson['name'].'<br>';
                    echo '<br>';
             }
    }

I don't know exactly if you need this condition $person['site'] == $girls['site'] ..if not you can delete it. That was just my feeling.

btw: you didn't show the $girls array so I just assume is just computed previously. And $data I assume is the $persons array that you are talking about.

1 Comment

sorry the girls is the persons array. i edited my question above to be sure and clear. :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.