According to the PHP documentation, array_unique removes duplicate values and sorts the values treated as string at first.
When you take the following snippet in mind:
// define a simple array of strings, unordered
$brands = [ "BMW", "Audi", "BMW", "Chrysler", "Daewoo"];
// distinct the values, and sort them
echo array_unique($brands, SORT_STRING);
I would expect the output to be:
expected: {"0":"Audi","1":"BMW","3":"Chrysler","4":"Daewoo"}
actual : {"0":"BMW","1":"Audi","3":"Chrysler","4":"Daewoo"}
The question is: why doesn't array_unique sort these values? Changing the sort_flags parameter to any of the four alternatives, or leaving it empty, has no effect either.
According to other SO questions, like "Why does array unique sort the values" I'm probably missing something obvious here. Also, using array_values(array_unique($brands)), as stated as an answer in this question doesn't seem to work either.
Update: As stated in the useful comments and answers, the sort_flags parameter is actually an inner compare behavior, or equality operator, sort of speak.
In manual they mean that values group by value and first key taken for eacj duplicated value.
you need something like this
$brands = array_unique($brands);
sort($brands);
SORT_STRING - is default
The documentation simply specifies how the algorithm is working internally to achieve its purpose. Why and how is well explained in the other question. It does not say that the returned result will be sorted as well. Sorting is outside the scope of this function and probably actually undesired most of the time.
For completeness, this is how'd you unique (is that a verb?) and sort the array:
$array = array_unique($array);
sort($array);
Related
I have the below snippet of code and I can't figure out why these two arrays won't merge - likely due to not understanding 100% how array_merge works. I'm expecting to see the duplicate, and merge the two into a single key. Running array_unique results in errors. Any ideas, or possibly an alternate solution to merge these two?
$a['12345']['label'] = '12345';
$a['12345']['type'] = 'Newspaper';
$b['12345']['label'] = '12345';
$b['12345']['type'] = 'Newspaper';
$result = array_merge($a, $b);
echo "<pre>";
print_r($result);
From the docs
If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended.
The short answer is that the merge is occurring, just not in the way you desire.
Because they would have the same keys. Try changing $b['12345'] to $b['12346'] and see if they merge.
This is probably a very trivial question, but please bear with me.
I am trying to read a lot of data into an array of associative arrays. The data contains a lot of empty arrays and arrays with keys set and but all null values. I want to ignore those and only push arrays with at least one key mapped to a non-null value. (The data comes from an excel sheet and it has lots of empty cells that are registered as "set" anyway.) So far I have tried:
if(!empty(${$small_dummy}))
array_push(${$big_dummy}, ${$small_dummy});
That gets rid of the empty arrays but not the ones where all keys map to null. Is there a better way to do this than looping through the entire array and popping all null values?
Judging by the code you have already, you can change:
if(!empty(${$small_dummy}))
to:
if(!empty(array_filter(${$small_dummy})))
That will filter out all empty values (values evaluating to FALSE to be precise) and check if the resulting array is empty. Also see the manual on array_filter().
Note that this would also filter 0 values so you might need to write a custom callback function for array_filter().
You can try if(!array_filter($array)) { also
This isn't an ideal approach, but array_sum will return 0 if all values can't be cast to a numeric value. So :
$small_dummy = array("a" => null, "foo", "", 0);
if(array_sum($small_dummy) === 0)
would pass. But this is only the way to go if you are expecting the values to be numeric.
Actually, if the problem is that the array keys have values and therefor are not passing as empty(), the go with array_values:
if(!empty(array_values(${$small_dummy})))
I'm trying to figure out what, if any, is a function to effectively remove a certain set of keys for an array.
I tried chaining array_keys and array_diff, but that just seemed to lead to me getting an array of array keys.
Basically, I want to remove the following keys:
"submit", "form_build_id", "form_token", "form_id", "op", "multi_reg_checkbox"
While preserving the structure of the original data.
Is array_filter what I am looking for? It sounds like it could be, but it seems like it is based on value only.
array_diff_key($arr, array_flip(array('foo', 'bar', ...)))
http://php.net/array_diff_key
The flip is just for convenience, you could also define the array of keys to remove using array('foo' => null, ...).
I have this array
$myArray=array(
'a'=>array('id'=>1,'text'=>'blabla1'),
'b'=>array('id'=>2,'text'=>'blabla2'),
'c'=>array('id'=>3,'text'=>'blabla3'),
'd'=>array('id'=>4,'text'=>'blabla4'),
);
and i want to sort the above array by the keys a,b,c,d, who exist in another array:
$tempArray=array('c','a','d','b');
How can I do that so the $myArray
looks like this:
$myArray=array(
'c'=>array('id'=>3,'text'=>'blabla3'),
'a'=>array('id'=>1,'text'=>'blabla1'),
'd'=>array('id'=>4,'text'=>'blabla4'),
'b'=>array('id'=>2,'text'=>'blabla2'),
);
thanks for helping me!
The simplest and likely most efficient way to do this is by iterating the array that holds the sort order and creating a new, sorted array:
$sorted = array();
foreach ($tempArray as $order) {
if (isset($myArray[$order])) {
$sorted[$order] = $myArray[$order];
}
}
print_r($sorted);
This works because associative arrays implicitly have an order of the order in which elements were added to the array.
See it working
EDIT
Any solution involving a sorting function will likely be much less efficient than this. This is because in order to do it you will need to use a function that takes a callback - this already has an implied overhead of the function call.
The sorting functions also work by comparing items, meaning that the complexity any of those solutions will be greater than that of this solution (the complexity of this is simply O(n)). Also, in order to derive the return value for the sorting function you would need to inspect the target array, finding the position of each of the keys being compared, for each comparison, adding even more complexity.
I don't understand this array accessing syntax:
$target[$segs[count($segs)]]
Is it really possible to use variables as multidimensional array keys?
That might result in an error, if $segs is a numerical array with continuous indices only.
Meaning, it would fail for:
array("foo","bar");
but work for
array("foo", 2=>"bar");
Assuming now, that we deal with the first case, then this would work:
$target[$segs[count($segs) - 1]]
First, count($segs) - 1 will be evaluated and return a number. In this case the last index of $segs (provided it is a numerical array).
$segs[count($segs) - 1] will therefore return the last element in $segs. And whatever that value is, will be used as index for $target[...].
To sum up: It is nested array indexing and evaluated inside out.
See it in action.
Whether or not such a method is necessary depends on the problem you are trying to solve. If you don't know where you would use such nested, variable array indexing then you probably don't need it.
That syntax is fine, provided $segs is an array. It's worth noting, though, that if you're using a numerically indexed array for $segs, calling count($segs) is a non-existent key because indexing starts at zero.