SitePoint Sponsor

User Tag List

Results 1 to 8 of 8
  1. #1
    SitePoint Addict jamus's Avatar
    Join Date
    Jul 2004
    Location
    Devon, UK
    Posts
    301
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Reorder array items to best match 'priority' order

    Hi,

    If I have an Array but I need to reorder it placing items the items that match the 'priority' items in the appropriate place. I am not concerned with the order of items that do not match.

    The priority list could be stored in an array but doesn't have to be.

    PHP Code:
    // priority 
    // massive = 1st
    // big = 2nd

    $sizes = array("other size""big""massive""another size");

    // required output

    $sizes = array("massive""big""other size""another size"); 
    I can find examples of reordering according to value. Do I need to chance the array - assigning each item a priority 'value' first? I'm not sure how if this is required or how to do this.

  2. #2
    Utopia, Inc. silver trophy
    ScallioXTX's Avatar
    Join Date
    Aug 2008
    Location
    The Netherlands
    Posts
    9,070
    Mentioned
    153 Post(s)
    Tagged
    2 Thread(s)
    PHP Code:
    $sizes = array("other size""big""massive""another size");

    $priorities = array('big''massive'); // need to be in reverse priority order! (left as an exercise to the reader)

    foreach ($priorities as $priority)
    {
        if ((
    $key array_search($priority$sizes)) !== false)
        {
            unset(
    $sizes[$key]);
            
    array_unshift($sizes$priority);
        }
    }

    var_dump($sizes);

    // array (size=4)
    //   0 => string 'massive' (length=7)
    //   1 => string 'big' (length=3)
    //   2 => string 'other size' (length=10)
    //   3 => string 'another size' (length=12) 
    All other sizes remain in their original order
    Rémon - Hosting Advisor

    SitePoint forums will switch to Discourse soon! Make sure you're ready for it!

    Minimal Bookmarks Tree
    My Google Chrome extension: browsing bookmarks made easy

  3. #3
    @php.net Salathe's Avatar
    Join Date
    Dec 2004
    Location
    Edinburgh
    Posts
    1,397
    Mentioned
    63 Post(s)
    Tagged
    0 Thread(s)
    Unless I'm misreading the question, there's really no need for looping or anything particularly complicated.

    Code php:
    $sizes = array("other size", "big", "massive", "another size"); 
    $priorities = array("massive", "big");
    $result = array_merge(array_intersect($priorities, $sizes), array_diff($sizes, $priorities));

    I'm sure we can detail what is happening if you're at all unsure.
    Salathe
    Software Developer and PHP Manual Author.

  4. #4
    SitePoint Addict jamus's Avatar
    Join Date
    Jul 2004
    Location
    Devon, UK
    Posts
    301
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thank you both.

    ScallioXTX - I think I understand your response though I haven't tried it. I tfind it interesting as I thought I might be able to use a For loop but had assumed it would have been on the Sizes Array rather than the Priorities Array.

    Salathe - You solution works perfectly. Though I have no idea what is going on! Would you mind explaining?

  5. #5
    SitePoint Addict bronze trophy
    Join Date
    Apr 2013
    Location
    Ithaca
    Posts
    351
    Mentioned
    6 Post(s)
    Tagged
    1 Thread(s)
    Your best shot is to use PHP's splpriorityqueue class, it does what you need.

  6. #6
    Keeper of the SFL StarLion's Avatar
    Join Date
    Feb 2006
    Location
    Atlanta, GA, USA
    Posts
    3,748
    Mentioned
    71 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by jamus View Post
    Salathe - You solution works perfectly. Though I have no idea what is going on! Would you mind explaining?
    Salathe's solution works on a couple of the quirks (if you want to call them that) or methods of how array_intersect and array_diff work (moreso the former).

    Array_Intersect takes multiple arguments in the form of arrays; It then intersects each array in turn with the initial array, to give a result array. Due to the way this function works, it will always check the first item of the array first (as defined by an array-shift; not by key value. Think of it like doing a FOREACH on the array), then the second. Thus by defining "massive" as the first element of the match-against array, you effectively prioritize it in the array_intersect, because it will search for "massive" first, then "big". It's an iterative construction. Note that you would NOT have gotten the same result if you'd array_intersected with the parameters the other way around!

    Array_diff does the same thing but in reverse; it finds everything that is in the initial array that isnt in the secondary. Again, order (and keys) is preserved; so the 'remainder' remains in the same order as when it went in (and missing any keys for which it had a deleted value) because of the order in which the parameters are given. The secondary ('input') array is first in the parameter list, so it defines the order of the output.

    So now you have two complimentary arrays (the intersected, or matched values, in order of the $priorities, and the diffed, or unmatched, in the original order).

    Array_merge takes the second array, plops it on the end of the first array. In this way you have prioritized the values you wanted to prioritize, in the order you wanted to prioritize them; the rest of the data you didnt care about, so it's just stuck on the end, unsorted.

    If this is still unclear let me know.
    Never grow up. The instant you do, you lose all ability to imagine great things, for fear of reality crashing in.

  7. #7
    @php.net Salathe's Avatar
    Join Date
    Dec 2004
    Location
    Edinburgh
    Posts
    1,397
    Mentioned
    63 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by StarLion View Post
    Salathe's solution works on a couple of the quirks (if you want to call them that) or methods of how array_intersect and array_diff work (moreso the former).
    Thanks for the explanation, StarLion. It saves me typing one.

    That said, I wouldn't at all say that I was using "quirks" of those functions (I'm not misusing them, or even using them in a useful way for which they were not intended); simply, "using the standard library effectively."

    Quote Originally Posted by Hall of Famer View Post
    Your best shot is to use PHP's splpriorityqueue class, it does what you need.
    Did you read the word "priority" and decided to chip in? Not that the SplPriorityQueue wouldn't be able to do the job, but it would be a strange choice.
    Salathe
    Software Developer and PHP Manual Author.

  8. #8
    SitePoint Addict bronze trophy
    Join Date
    Apr 2013
    Location
    Ithaca
    Posts
    351
    Mentioned
    6 Post(s)
    Tagged
    1 Thread(s)
    Nope, I did read the topic carefully before posting my response so it's not like I recommended using priority queue without a reason. PHP built-in arrays are bad practices and not even object oriented, in my application I use splfixedarray(or more precisely a subclass of splfixedarray) for arrays, it's even faster than PHP's built in arrays. That's for numerically indexed arrays, associative arrays really should've been objects to begin with so I pretty much never use it.

    In fact, for the OP's application I'd say extending splpriorityqueue to provide a custom compare method that overrides splpriorityqueue's compare method will work out the best. I have my own priority queue class too, but it's different from splpriorityqueue in a way that it's compare method is delegated to comparator classes so that instead of subclassing priority queue class, you simply provide different comparator class to decide how priority is calculated and compared. I personally like this approach better than splpriorityqueue's, but it's a matter of choice.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •