Advertisement
Advertisement


Given that I have a hash of id(key) and countries(values) sorted alphabetically, what is the best way to bubble up an entry to the top of the stack?


Question

This is a php example, but an algorithm for any language would do. What I specifically want to do is bubble up the United States and Canada to the top of the list. Here is an example of the array shortened for brevity.

array(
  0 => '-- SELECT --',
  1 => 'Afghanistan',
  2 => 'Albania',
  3 => 'Algeria',
  4 => 'American Samoa',
  5 => 'Andorra',)

The id's need to stay intact. So making them -1 or -2 will unfortunately not work.

2011/11/13
1
3
11/13/2011 2:21:50 PM


My shortcut in similar cases is to add a space at the start of Canada and two spaces at the start of United States. If displaying these as options in a SELECT tag, the spaces are not visible but the sorting still brings them to the front.

However, that may be a little hacky in some contexts. In Java the thing to do would be to extend StringComparator, override the compare() method making the US and Canada special cases, then sort the list (or array) passing in your new comparator as the sort algorithm.

However I would imagine it might be simpler to just find the relevant entries in the array, remove them from the array and add them again at the start. If you are in some kind of framework which will re-sort the array, then it might not work. But in most cases that will do just fine.

[edit] I see that you are using a hash and not an array - so it will depend on how you are doing the sorting. Could you simply put the US into the hash with a key of -2, Canada with -1 and then sort by ID instead? Not having used PHP in anger for 11 years, I don't recall whether it has built-in sorting in its hashes or if you are doing that at the application level.

2008/09/04

$a = array(
    0 => '- select -',
    1 => 'Afghanistan',
    2 => 'Albania',
    3 => 'Algeria',
    80 => 'USA'
);

$temp = array();
foreach ($a as $k => $v) {
    $v == 'USA'
        ? array_unshift($temp, array($k, $v))
        : array_push($temp, array($k, $v));
}
foreach ($temp as $t) {
    list ($k, $v) = $t;
    echo "$k => $v\n";
}

The output is then:

80 => USA
0 => - select -
1 => Afghanistan
2 => Albania
3 => Algeria
2008/09/04

You can not change the order of elements within the same array by "moving" an item around. What you can do it to build a new array that first has your favourite items and then adds anything else from the original countries array at the end:

$countries = array(
  0 => '-- SELECT --',
  1 => 'Afghanistan',
  2 => 'Albania',
  3 => 'Algeria',
  4 => 'American Samoa',
  5 => 'Andorra',
  22 => 'Canada',
  44 => 'United States',);

# tell what should be upfront (by id)
$favourites = array(0, 44, 22);

# add favourites at first
$ordered = array();
foreach($favourites as $id)
{
    $ordered[$id] = $countries[$id];
}

# add everything else
$ordered += array_diff_assoc($countries, $ordered);

# result
print_r($ordered);

Demo

2011/11/13

It's been ages since I don't know how to code. But yes.

array_unshift($queue, "United States", "Canada");
print_r($queue);

array_unshift — Prepend one or more elements to the beginning of an array

2019/05/22

Source: https://stackoverflow.com/questions/44272
Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]