Array sorting of key values [duplicate] - php

This question already has answers here:
Preserve key order (stable sort) when sorting with PHP's uasort
(6 answers)
Closed 10 years ago.
I have a poll on my website. For it I put the results into an array such as this:
[Answer1] => "0",
[Answer2] => "1",
[Answer3] => "0",
[Answer4] => "0"
The choice is the key and the number of votes is the value. Essentially when the results show I want to order by the number of votes and then also keep the same sort. So if no votes it would show in the order:
Answer1
Answer2
Answer3
Answer4
But, with "Answer2" having 1 vote it would show:
Answer2
Answer1
Answer3
Answer4
I have tried creating a custom usort function but am having no luck.
Can anybody help me with the logic how to do it please (i can do the PHP myself)?

As you are using an associative array what you are looking for is called a stable sort.
PHP's standard array sorting functions use an unstable implementation of quicksort so as you have found they will not help you here.
You could accomplish this though using array_multisort. By sorting by BOTH the value and the key.
With your data structure you currently have you could not do this with any of the u*sort functions BUT if you modified the data structure and added another dimension so that it looked like the following then you could:
array(
array(
'answer' => 1,
'votes' => 0,
),
array(
'answer' => 2,
'votes' => 1,
),
)
So essentially the comparison function would just need to take into account both sub-indexes.
hope that helps

You want the php function "asort":
http://uk.php.net/manual/en/function.asort.php
it sorts the array, maintaining the index associations.
I've just noticed you're using a standard array (non-associative). if you're not fussed about preserving index associations, use sort( ):
http://uk.php.net/manual/en/function.sort.php

I think asort() will work..
asort($your_array);

Looks like I misread the question.
asort() will sort the array by value, so the highest votes will be first in the array.
thus the result will be:
[Answer2] => "1",
[Answer1] => "0",
[Answer3] => "0",
[Answer4] => "0"
or an even more complete example
[Answer2] => "42",
[Answer3] => "29",
[Answer1] => "18",
[Answer4] => "9"

Related

Pushing array into multidimensional array (php) [duplicate]

This question already has an answer here:
array_push won't give an array, prints out integer value
(1 answer)
Closed 4 years ago.
I've attempted many different ways to push an array into a multidimensional array, including array_push(), $array['index'] = $toPush but I keep being met with quite unexpected results. I have used both var_dump() and print_r() as detailed below in an attempt to debug, but cannot work out the issue.
My reasoning behind is to run a while loop to pull game id's and game names and store these in an assoc. array, and then push them into my main array.
$games_array = array
(
"games" => array
(
array("id"=>"1", "game"=>"first game");
array("id"=>"2", "game"=>"second game");
)
);
// a while loop would run here and update $game_to_add;
$game_to_add = array("id"=>"$game['id']", "game"=>"$game['title']");
$games_array = array_push($games_array['games'], $game_to_add);
In this example, the while() would update the ID and the Game inside of $game_to_add
But, whenever I attempt this it simply overwrites the array and outputs an integer ( example: int(3) )
I don't understand what the problem is, any explination would be appreciated as I cannot find a question specifically for this.
My actual test code:
$games_array = array( "games" => array(
array("id" => "1", "name" => "Star feathers"),
array("id" => "2", "name" => "chung fu")
)
);
$another_game = array("id" => "3", "name" => "some kunt");
$games_array = array_push($games_array["games"], array("id" => "3", "name"
=>"some game"));
var_dump($games_array);
You're assigning the return value of array_push to the games array.
The return value of array_push is the amount of elements after pushing.
Just use it as
array_push($array, $newElement);
(Without assignment)
If you're only pushing one element at he time, $array[] = $newElement is preferred to prevent overhead of the function call of array_push

php, array_merge_recursive works well with string keys only

$array1 = [
'1' => '11',
'b' => 1,
3 => 33,
8 => 8
];
$array2 = [
'1' => '22',
'b' => 2,
3 => 44,
9 => 9
];
$merged = array_merge_recursive($array1, $array2);
and the result is:
array(7) {
[0]=>
string(2) "11"
["b"]=>
array(2) {
[0]=>
int(1)
[1]=>
int(2)
}
[1]=>
int(33)
[2]=>
int(8)
[3]=>
string(2) "22"
[4]=>
int(44)
[5]=>
int(9)
}
so lets take a glance: the only part is the 'b' keys, they are actually works. I dont want to overwrite anything of it but putting them together to an array. Thats good! But then keys the other numeric keys (int or string) are screwed up.
I want to have this as result:
[
'1' => ['11', '22']
'b' => [1, 2]
[3] => [33, 44]
[8] => 8,
[9] => 9
]
possible?
EDIT: of course keys "1" and 1 - string vs int key are the same
Let's break down this question into to separate problems:
When a key in the second array exist in the first array, you want to create an array and make the value the first element of that array.
To be honest, I don't know an easy way of solving this. I'm not sure there is one. And even if, I'm not sure you really want it. Such a function will lead to arrays having values that are a string or an array. How would you handle such an array?
Update: Well, there is one. Your example already shows that array_merge_recursive will convert values with a string key into an array. So 1 => 'foo' would be 0 => 'foo', but 'foo' => 'bar' will end up as 'foo' => ['bar']. I really don't understand this behaviour.
Using string keys would help you out in this case, but after learning more about array_merge_recursive I decided to avoid this function when possible. After I asked this question someone filed it as a bug in it since PHP 7.0, since it works differently in PHP 5.x.
You want to keep the keys, while array_merge_resursive doesn't preserve integer keys, while it does for integer keys:
If the input arrays have the same string keys, then the values for
these keys are merged together into an array, and this is done
recursively, so that if one of the values is an array itself, the
function will merge it with a corresponding entry in another array
too. If, however, the arrays have the same numeric key, the later
value will not overwrite the original value, but will be appended.
To make it worse, it handles differently when handling the nested arrays:
$array1 = [30 => [500 => 'foo', 600 => 'bar']];
$array2 = [];
array_merge_recursive($array1, $array2);
//[0 => [500=> 'foo', 600 => 'bar']];
So effectively, array_merge_resursive isn't really resursive.
Using array_replace_resursive solves that problem:
array_replace_recursive($array1, $array2);
//output:
//array:5 [
// 1 => "22"
// "b" => 2
// 3 => 44
// 8 => 8
// 9 => 9
//]
Please note that PHP is very consistent in being inconsistent. While array_merge_recursive isn't recursive, array_replace_recursive doesn't replace (it also appends):
If the key exists in the second array, and not the first, it will be
created in the first array.
In many cases this is desired behavior and since naming functions isn't PHP's strongest point, you can consider this as a minor issue.
Can you rely on a native function to return your exact desired output? No. At least not in any version as of the date of this post (upto PHP8.1).
The good news is that crafting your own solution is very simple.
Code: (Demo)
foreach ($array2 as $key => $value) {
if (!key_exists($key, $array1)) {
$array1[$key] = $value;
} else {
$array1[$key] = (array)$array1[$key];
$array1[$key][] = $value;
}
}
var_export($array1);
I suppose I am less inclined to recommend this output structure because you have potentially different datatypes on a given level. If you were building subsequent code to iterate this data, you'd need to write conditions on every level to see if the data was iterable -- it just feels like you are setting yourself up for code bloat/convolution. I'd prefer a result which has consistent depth and datatypes.

How can I find uniqueness in an array (php) [duplicate]

This question already has answers here:
How to check if all values in array are identical?
(6 answers)
Closed 9 years ago.
I have two possible configurations of an array in php like the following:
$array = array(
"0" => "137",
"1" => "137",
"2" => "137",
"3" => "137",
"4" => "137"
);
and
$array = array(
"0" => "137",
"1" => "200",
"2" => "31",
"3" => "19",
"4" => "400"
);
I am not trying to compare the arrays to each other.
It does not matter that the specific numbers are "137" or any other number for that matter, what I need to know is how to programatically determine that the first array is "true" because all of its values are the same. The second array is "false" because they are different. The second one could have any random set in it as well, including a bunch of the same number, and one different one.
I don't care really about what number is different, only if they are all the same. I'm researching now, but I am not sure what to look for, term-wise.
if (count(array_unique($array)) > 1) {
// not all elements are the same
}
You can use the array_unique function php array_unique
if the count of the resulting array is 1 then all values are the same.
Or it may be best to just loop through the array to until you find a value that is different, this has a worse case o(n)
EDIT: Note that count(array_unique($array)) is cleaner but less eficient, still o(n) though (allways o(n) not just worse case).

Php array rebuild

I got an array looking like this:
array("canv" => array(1 => "4", 2 => "6", 3 => "9", 4 => "7");
I need it to look like this:
array("canv" => array("4", "6", "9", "7");
so I can easly check if the value exist this way:
if(isset($result["canv"][$gid])) where $gid is a number from "4", "6", "9", "7".
How can it be done?
This will flip the values to become keys and vice versa:
$result["canv"] = array_flip($result["canv"]);
So instead of
array(1 => "4", 2 => "6", 3 => "9", 4 => "7")
you'll have
array("4" => 1, "6" => 2, "9" => 3, "7" => 4)
But then again think about building the original array in the desired way and only do this if you can't afford that.
It won't work because you are looking for array keys, while 4, 6, 9 and 7 are the values, but if you use array_search($gid, $result['canv']) you'll find the index of $gid or false if $gid's value is not in the list.
So this will work:
if(array_search($gid, $result['canv']) !== false){
//Do Stuff
}
Without any modification, with your existing array, you can check it as:
if (in_array($gid, $result["canv"])) {
// $gid is in the array
}
Logically, if canv is to be an array of those values, the values should be array members rather than the array keys which point to members. You are asking to use them as array keys. Unless you want them to behave as keys later on, whereby they will be used to point to array values, you should not change them now.
Then I don't think you want it to look like that.... You want it to look like this:
array(
"canv" => array(
4 => "value",
6 => "value",
9 => "value",
7 => "value"
)
)
You did not specify what values you want, but it may not matter. You can arrive at at that however you want, but if you wind up with an array with (4,6,9,7) in it, you can just do array_flip and it will exchange the keys with the values.

Sort array by keys which are in Ymd format with no delimiting characters [duplicate]

This question already has answers here:
How to sort an array by keys in an ascending direction?
(3 answers)
Closed 6 months ago.
I have an array with keys as date in this format.
$arr = array(
"20110805" => "2",
"20100703" => "5",
"20110413" => "3",
"20100805" => "4",
"20100728" => "6",
"20090416" => "7",
"20080424" => "8",
"20110819" => "1",
);
How can I sort this array by key?
With the dates in that format, an alphabetical comparison will work just fine. Use the PHP function ksort.
ksort($arr);
A slightly more complex solution, which nonetheless works for almost any date format, is based on the uksort function.
First we define a callback function that compares two dates (comparator):
function compare_date_keys($dt1, $dt2) {
return strtotime($dt1) - strtotime($dt2);
}
Now we can use the just defined function as the second parameter in uksort, as in the example below:
uksort($arr, "compare_date_keys");
As a result the function will treat the key as a date and sort the array in ascending order (less recent first).
Note that we can easily tweak the comparator to support different use cases. For example, sorting by date descending (most recent first) can be accomplished by simply replacing the function's return expression with the following:
return strtotime($dt2) - strtotime($dt1);
Just this single line of code:
ksort($arr);

Categories