Re-sorting array via array keys? - php

I have two arrays, $country and $redirect with each entry corresponding with it's exact counterpart e.g. $redirect[1] and $country[1].
After un-setting values throughout the array, I might be left with, for example, an array where only $var[4] and $var[2] are set. I want to re-assign array keys from 0 upwards, so that $var[2] would have it's key re-assigned to $var[0] and $var[4] re-assigned to $var[1].
Essentially the sort() function, but sorting by current array key, as oppose to the numeric/string value of an array.
Is this possible?
Any answers or advice would be greatly appreciated ;)!
UPDATE:
I've attempted to use both ksort() and array_values(), however I'm not sure they're really what I need, as I plan on using the size_of() function.
My code:
$var = array(2 => "value_1", 4 => "value_2", 6 => "value_3");
ksort($var);
for($i = 0, $size = sizeof($var); $i < $size; $i++) {
$var[$i] = "foo";
}
var_dump($var);
Returns:
array(5) { [2]=> string(3) "foo" [4]=> string(7) "value_2" [6]=> string(7) "value_3" [0]=> string(3) "foo" [1]=> string(3) "foo" }
Any additional ideas/answers on how I could get this to work would be greatly appreciated!

Use array_values() (returns "sorted" array):
$var = array(2 => "value_1", 4 => "value_2", 6 => "value_3");
$var = array_values($var);
for($i = 0, $size = sizeof($var); $i < $size; $i++) {
$var[$i] = "foo";
}
var_dump($var);

Related

Array comparision in php to get only difference

Following Below are two arrays which i wanna compare and remove the same values something like array_diff() Function and i want to store the result in third array
$array1 = Array([0] => Array([a] => XYZ,[b] => ABC))
$array2 = Array([0] => Array([a] => XYZ,[b] => ABC),[1] => Array([a] => PQR,[b] => XYZ))
$array3 = array_diff($array1,$array2);
//$array3 value must return this value Array([1] => Array[a]=> PQR,[b] => XYZ)
I don't know what i am doing wrong but i am getting error that array cannot be converted into string. Can anyone help me with this?
Thanks in advance
If you are sure that your $array2 will always contain more elements than $array1 then here is your solution:
$array1 = array(array('a' => 'XYZ','b' => 'ABC'));
$array2 = array(array('a' => 'XYZ','b' => 'ABC'),array('a' => 'PQR','b' => 'XYZ'));
$limit = count($array2);
$array3 = array();
for($i=0;$i<$limit;$i++){
if(empty($array1[$i]))
$array3[] = $array2[$i];
$array3[] = array_diff($array1[$i],$array2[$i]);
}
foreach($array3 as $k=>$a3){
if(empty($a3)||($a3===NULL))
continue;
$result[$k] = $a3;
}
var_dump($result); //array(1) { [1]=> array(2) { ["a"]=> string(3) "PQR" ["b"]=> string(3) "XYZ" } }
Please note that array_diff works on 1D array and you was providing 2D arrays as parameter and that's why it wasn't working.
Also your way of defining $array1 and $array2 is wrong, please check this solution for right syntax.
I hope it helps

PHP: How are array items passed to the value compare function when using usort()?

I'm trying to understand how the items from my array are passed to my value compare function when using usort(). A printout of the values of $x and $y for each iteration follows:
Iteration 1:
// $x
array(2) { ["k1"]=> int(21) ["k2"]=> string(1) "e" }
// $y
array(2) { ["k1"]=> int(920) ["k2"]=> string(1) "z" }
Iteration 2:
// $x
array(2) { ["k1"]=> int(842) ["k2"]=> string(1) "t" }
// $y
array(2) { ["k1"]=> int(21) ["k2"]=> string(1) "e" }
Iteration 3:
// $x
array(2) { ["k1"]=> int(920) ["k2"]=> string(1) "z" }
// $y
array(2) { ["k1"]=> int(21) ["k2"]=> string(1) "e" }
Iteration 4:
// $x
array(2) { ["k1"]=> int(842) ["k2"]=> string(1) "t" }
// $y
array(2) { ["k1"]=> int(920) ["k2"]=> string(1) "z" }
My data:
$data = array(
array( 'k1' => 920, 'k2' => 'z' ),
array( 'k1' => 21, 'k2' => 'e' ),
array( 'k1' => 842, 'k2' => 't' )
);
My custom function:
function value_compare_func( $x, $y ) {
if ( $x['k1'] > $y['k1'] ) {
return true;
} elseif ( $x['k1'] < $y['k1'] ) {
return false;
} else {
return 0;
}
}
Sort the array:
usort( $data, 'value_compare_function' );
For the first iteration, $x['k1'] is $data[1]['k1'] and $y['k1'] is $data[0][k1]. Why aren't the items from my $data array passed to value_compare_func() in order? For example, I would have expected $x['k1'] to be $data[0]['k1'] and $y['k1'] to be $data[1]['k1'] for the first iteration, but this isn't the case.
The answer to how these items are passed to the comparison function would require understanding the quicksort algorithm. The gist of it is that some element in the array is assigned as a pivot (it could be any element at all really, but in efficient implementation's it's typically the median element) and then comparison on either side of the pivot is done to sort the array.
This is the underlying implementation of usort in PHP, basically.
So trying to observe the order in which elements are passed to the comparison function is relatively useless. The order is completely unimportant. What's important is that you can rest assured they will always be sorted correctly according to what your callback function returns.
The important thing to note here is that the manual explicitly warns against returning values from the callback that are not integers for a very specific reason (they will be cast to integers) and in your example here you are returning a boolean false from the callback which will become 0 when cast to an integer. Since 0 indicates both values are equal you will not and should not expect a properly sorted array here.
Always make sure to return an integer value of 1 when $a > $b, an integer value of -1, when $a < $b and an integer value of 0 when $a == $b from your callback.
The compare function should return a numerical value. Since you return booleans, the comparison becomes unpredictable as false == 0 and so the distinction between the two is lost in sorting.
You should change your code as follows:
function value_compare_func( $x, $y ) {
if ( $x['k1'] > $y['k1'] ) {
return 1;
} elseif ( $x['k1'] < $y['k1'] ) {
return -1;
} else {
return 0;
}
}
... and the results will be more logical.

How to merge two arrays by its values in PHP?

What I need is really simple:
I have two arrays like that:
<?php
$a1 = [1,2,3];
$a2 = [2,3,4];
I need to combine them so that the result is:
$result = [1,2,3,4];
I've tried array_merge but the result was [1,2,3,2,3,4]
You can find an answer to this here: Set Theory Union of arrays in PHP
By expanding on your current method. You can call array_unique and sort on the resulting array.
$a = [1,2,3];
$b = [2,3,4];
$result = array_merge($a, $b);
$result = array_unique($result);
sort($result);
This will result in:
array(4) {
[0] = int(1) 1
[1] = int(1) 2
[2] = int(1) 3
[3] = int(1) 4
}
function merges(/*...*/){
$args=func_get_args();
$ret=array();
foreach($args as $arg){
foreach($arg as $key=>$v)
{
$ret[$key]=$v;
}
}
return $ret;
}
untested, but i guess this would work.. will delete all duplicate keys and return the last key/value pair it found of duplicates
This might be what you are looking for
$result = $a1 + $a2 //union operation
reference
Array Operations
Example
$a = array("a" => "apple", "b" => "banana");
$b = array("a" => "pear", "b" => "strawberry", "c" => "cherry");
$c = $a + $b; // Union of $a and $b
echo "Union of \$a and \$b: \n";
var_dump($c);
Ouput
Union of $a and $b:
array(3) {
["a"]=>
string(5) "apple"
["b"]=>
string(6) "banana"
["c"]=>
string(6) "cherry"
}

PHP array_merge() function

I have some problems during working with arrays using array_merge function. Here an example:
First example:
$first = array('01' => 1, '03' => 73);
$second = array('14'=>11, '15' => 23);
var_dump(array_merge($first, $second));
Result is:
array(4) { ["01"]=> int(1) ["03"]=> int(73) [0]=> int(11) [1]=> int(23) }
Expected:
array(4) { ["01"]=> int(1) ["03"]=> int(73) [14]=> int(11) [15]=> int(23) }
Second example:
$first = array('01'=>3, '03'=>10);
$second = array('05'=>44, '07'=>3);
var_dump(array_merge($first,$second));
Result is(as expected):
array(4) { ["01"]=> int(3) ["03"]=> int(10) ["05"]=> int(44) ["07"]=> int(3) }
Third example:
var_dump(array_merge(array("somekey"=> array("some value"))));
Result is(as expected):
array(1) { ["somekey"]=> array(1) { [0]=> string(10) "some value" } }
Fourth example:
var_dump(array_merge(array("34"=> array("some value"))));
Result is:
array(1) { [0]=> array(1) { [0]=> string(10) "some value" } }
Expected:
array(1) { [0]=> array(1) { ["34"]=> string(10) "some value" } }
var_dump(array_merge(array("34"=> array("some value"))));
As you can see from third and fourth examples I set string for keys but the result was not as expected.
What is wrong or incorrect of understanding?
Thanks for helping.
Edited. Why (example first and second) the result is different, but the keys are string and consist of only with digest?
Quoting from the manual:
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.
Values in the input array with numeric keys will be renumbered with
incrementing keys starting from zero in the result array.
Keys with a leading zero are being treated as strings, while numeric keys without a leading zero are being treated as numeric
If you want to retain the keys exactly as they are:
$first = array('01' => 1, '03' => 73);
$second = array('14'=>11, '15' => 23);
var_dump(
array_combine(
array_merge(
array_keys($first), array_keys($second)
),
array_merge(
$first, $second
)
)
);
as long as keys are unique between $first and $second
Definition : Merges the elements of one or more arrays together so that the values of one are appended to the end of the previous one. It returns the resulting array.
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.
Values in the input array with numeric keys will be renumbered with incrementing keys starting from zero in the result array.
INPUT
<?php
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
print_r($result);
?>
OUTPUT
Array
(
[color] => green
[0] => 2
[1] => 4
[2] => a
[3] => b
[shape] => trapezoid
[4] => 4
)
Hope it helps:)
Try array_merge() like below:-
$first = array('01' => 1, '03' => 73);
$second = array('14'=>11, '15' => 23);
$output = array_merge($first, $second);
print_r($output);
EDIT:-
$first = array('01' => 1, '03' => 73);
$second = array('14'=>11, '15' => 23);
$output = $first + $second;
print_r($output);

Get top x items from an array php

array(10) { [0]=> int(5)
[1]=> int(8)
[2]=> int(2)
[3]=> int(0)
[4]=> int(1)
[5]=> int(9)
[6]=> int(1)
[7]=> int(0)
[8]=> int(5)
[9]=> int(4)
}
Ok, so I have an array as above. What I would like to do is get the top x items, change them into 1 and the rest into 0 without messing with the keys so that I can implode it back in the correct order. So if I want top 5, the result should be something like:
array(10) { [0]=> int(1)
[1]=> int(1)
[2]=> int(0)
[3]=> int(0)
[4]=> int(0)
[5]=> int(1)
[6]=> int(0)
[7]=> int(0)
[8]=> int(1)
[9]=> int(1)
}
I tried using sort, but I think it messes up the keys.
Any help would be appreciated. Thanks.
Uhm, I don't know If I understand question, but maybe:
for ($i = 0; $i < $topX; $i++)
$arr[$i] = (int)1;
for ($i = $topX+1;$i < count($arr); $i++)
$arr[$i] = (int)0;
Or add IF:
for ($i = 0; $i < count($arr); $i++)
$arr[$i] = ($arr[$i] < $maxVal) ? (int)1 : (int)0;
Well, I guess this is what you are looking for. I believe that the code is self-explain because I have comment all the important concept in the code.
<?php
function top(&$arr, $top, $start = 0)
{
if (count($arr) > $start) {
// count the number of element that larger
// than the element at start position
$count = 0;
for($i = $start + 1; $i < count($arr); $i++) {
if ($arr[$start] < $arr[$i]) $count++;
}
// if there are more than [$top] number of element
// that is larger than this element
// it cannot be in the [$top] largest number
if ($count >= $top) {
$arr[$start] = 0;
} else {
$arr[$start] = 1;
$top -= 1;
}
// continue to next element
top($arr, $top, $start + 1);
}
}
$arr = array(5, 8, 2, 0, 1, 9, 1, 0, 5, 4);
top($arr, 5);
var_dump($arr);
?>
asort() sort an array and maintain index association.
PHP has some pretty neat array-functions you can work with. Here's one approach:
<?php
function change_top_items($array, $top_x) {
// first, sort the values and preserve the keys
uasort($array, function($a, $b) {
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
});
// put the top x values in an array
$compare = array_slice($array, -$top_x);
// now walk through the original array
$modified = array_map(function($value) use ($compare) {
// if the current value is in the top x array
// set it to 1, else set it to 0
return in_array($value, $compare) ? 1 : 0;
}, $array);
// now sort the modified array by keys again and return it
ksort($modified);
return $modified;
}
$a = [5, 8, 2, 0, 1, 9, 1, 0, 5, 4];
print_r(change_top_items($a, 5));
And that's pretty much it.
Output:
Array
(
[0] => 1
[1] => 1
[2] => 0
[3] => 0
[4] => 0
[5] => 1
[6] => 0
[7] => 0
[8] => 1
[9] => 1
)
Here's a working exapmple: http://3v4l.org/HI2EH - As you can also see there, I've used a syntax which is only valid for PHP 5.4+. This concerns the short array notation and the use of closures. But this code can easily be converted into a syntax of the previous PHP versions.

Categories