How to change a multidimension array element with a function - php

I have an array like this:
<?php
$arr = [
'a' => [
'a1' => [
'A11', 'A12', 'A13'
]
]
];
I can change the A13 element in an easy way:
$arr['a']['a1'][2] = 'A13 NEW';
But I want to do this with a function, something like this:
f($arr, ['a', 'a1', 2], 'A13 New');
I write this function using eval and I don't like it.
<?php
function f(&$array, $index, $value) {
$e = '$array';
for ($i = 0, $l = count($index); $i < $l; $i++) {
$e .= '[$index[' . $i . ']]';
}
$e .= ' = $value;';
// now we have `$e` like this
// $array[$index[0]][$index[1]][$index[2]] = $value;
eval($e);
}
How can I write this function without using eval?

$arr = array(
'a' => array(
'a1' => array(
'A11', 'A12', 'A13'
)
)
);
function f(&$arr, $index, $value) {
$tmp = &$arr;
foreach ($index as $key) {
$tmp = &$tmp[$key];
}
$tmp = $value;
}
f($arr, array('a', 'a1', 2), 'A13 New');
//$arr['a']['a1'][2] = 'A13 NEW';
var_dump($arr);

Related

I try to sort an array using sort() but it fails

if ( $_GET['_value'] == 'moto' )
{
$array[] = array('1' => 'Yamaha');
$array[] = array('2' => 'Suzuki');
$array[] = array('3' => 'Triumph');
$array[] = array('4' => 'KTM');
$array[] = array('5' => 'Honda');
$array[] = array('6' => 'Harley Davidson');
$array[] = array('7' => 'Buell');
$array[] = array('8' => 'MV Agusta');
$array[] = array('9' => 'Ducati');
$array[] = array('10' => 'Other');
}
$array = sort($array);
echo json_encode( $array );
that is the code i have and its pulled by a chained dropdown.
I want it to return the values sorted alphabetically but based on the code you see it returns an empty array. what could be the mistake I am making /
Your code fails because you have an array of arrays here.
You should either search for "sort php array by sub-array key"
Or you can try something like:
$array[1] = 'Yamaha';
$array[2] = 'Suzuki';
// ...
sort($array);
echo json_encode($array);
Your array contains arrays, hence cannot be sorted, try:
$array[1] = 'Yamaha';
$array[2] = 'Suzuki';
then sort($array)
You can use uasort() function
like:
function cmp($a, $b) {
$a = reset($a);
$b = reset($b);
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
uasort($array, 'cmp')
It's not at all pretty but this does the job.
Unless you're constrained otherwise you should really use some of the other suggestions.
<?
if ( $_GET['_value'] == 'moto' ) {
$array[] = array('1' => 'Yamaha');
$array[] = array('2' => 'Suzuki');
$array[] = array('3' => 'Triumph');
$array[] = array('4' => 'KTM');
$array[] = array('5' => 'Honda');
$array[] = array('6' => 'Harley Davidson');
$array[] = array('7' => 'Buell');
$array[] = array('8' => 'MV Agusta');
$array[] = array('9' => 'Ducati');
$array[] = array('10' => 'Other');
foreach($array as $i => $v)
{
$v = array_values($v);
$sort[] = $v[0];
}
sort($sort);
$c = 0;
foreach($sort as $i => $v)
{
$c++;
$sorted[] = array($c=>$v);
}
echo json_encode($sorted);
}
?>

How do I make pairs of array values?

Consider the following array as input:
$input = array('A', 'B', 'C', 'D');
I'm looking for a way to make loop though this array, writing down every possible pair of two values. In this example: AB AC AD BC BD CD. Please not that BA doesn't count as a pair, since AB is already mentioned:
$output = array(
'A' => 'B',
'A' => 'C',
'A' => 'D',
'B' => 'C',
'B' => 'D'
);
Any input on how to get this started is appreciated!
$output=array();
for ($i=0;$i<sizeof($input);$i++) {
$k=$input[$i];
for ($j=$i+1;$j<sizeof($input);$j++) {
$v=$input[$j];
$output[]=array($k=>$v);
}
}
Edit
As of your comment, the restructured output
$output=array();
//See below
for ($i=0;$i<sizeof($input);$i++) {
$k=$input[$i];
$v=array();
for ($j=$i+1;$j<sizeof($input);$j++) {
$v[]=$input[$j];
}
$output[]=array($k=>$v);
}
This will give you 'D'=>Array() as a last row, if you don't want hti you have to change
for ($i=0;$i<sizeof($input);$i++) {
to
for ($i=0;$i<sizeof($input)-1;$i++) {
something like this maybe;
$input = array('A', 'B', 'C', 'D');
$input_copy = $input;
$output = array();
$i = 0;
foreach($input as $val) {
$j = 0;
foreach($input_copy as $cval) {
if($j < $i) break;
$output[] = array($val => $cval);
$j++;
}
$i++;
}
$output = array(
0 => array('A' => 'A'),
1 => array('A' => 'B'),
2 => array('A' => 'C'),
...
);
Note that your output array is impossible, as the key is overwritten each time
This won't be possible in PHP, as PHP array can have only unique keys.
You can get output as
$output = array(
'A' => array('B','C','D'),
'B' => array('C','D')
);
$input = array('A', 'B', 'C', 'D');
foreach($input as $key => $value){
$tempKey = $key;
for($key +1 ; $key < count($input) ; $key++){
$result[$tempKey][] = $input[$key];
}
}
You can use this generic method:
function combine($inputArray, &$outputArray, $index, $combLen) {
global $outstr;
for ($i = $index; $i < count($inputArray); $i++) {
$outstr.=$inputArray[$i];
if(strlen($outstr) == $combLen) {
$outputArray[]= $outstr;
}
combine($inputArray, $outputArray, $i + 1, $combLen);
$outstr = substr($outstr, 0, strlen($outstr)-1);
}
}
See it on ideone
if you need to work with pairs as arrays
$pairs = [];
foreach($a as $k => $v) {
foreach(array_slice($a, $k + 1) as $k2 => $v2) {
$pairs[] = [$v, $v2];
}
}

How to get the uneven keys from an array?

I have to create a function that copy the array(that i pass to the function) with only uneven keys. Example:
$a = array(
'0' => '0',
'one => 'one',
'1' => '1',
'two' => 'two'
)
I have to get:
$result = array(
'one => 'one',
'two' => 'two'
)
I have created the follow function, it works, but maybe I need to optimize it(maybe exists a function that does this job). Advice?
private clean($values){
$vv = array();
$keys = array_keys($values);
for($i=1; $i < count($values); $i+=2) $vv[$keys[$i]] = $values[$keys[$i]];
return $vv;
}
Thanks
$even = range(0, count($array), 2);
source
UPDATE:
for ($i = 0, $c = count($array); $i <= $c; $i = $i + 2) {
$even = array_push($even, $array[$i]);
}
Try
$outputArray = array();
$keyToAdd = false;
foreach( $inputArray as $key => $value ) {
if( $keyToAdd ) {
$outputArray[$key] = $value;
}
$keyToAdd = !$keyToAdd;
}

PHP's array functions?

Out of this:
$arr = array(
array('boo', 4),
array('boo', 1),
array('foo', 2),
array('foo', 6)
);
how best calculate into this?:
$arr = array(
'boo' => 5,
'foo' => 8
);
$sum = array();
for ( $i = 0; $i < count( $arr ); $i++ )
{
if ( !isset( $sum[ $arr[$i][0] ] )
$sum[ $arr[$i][0] ] = 0;
$sum[ $arr[$i][0] ] += $arr[$i][1];
}
print_r( $sum );
$arr = array(
array('boo', 4),
array('boo', 1),
array('foo', 2),
array('foo', 6)
);
Then:
$arr2 = array();
foreach($arr as $value) {
if(isSet($arr2[$value[0]])) $arr2[$value[0]] += $value[1];
else $arr2[$value[0]] = $value[1];
}

Check and return duplicates array php

I would like to check if my array has any duplicates and return the duplicated values in an array.
I want this to be as efficient as possible.
Example:
$array = array( 1, 2, 2, 4, 5 );
function return_dup($array); // should return 2
$array2 = array( 1, 2, 1, 2, 5 );
function return_dup($array2); // should return an array with 1,2
Also the initial array is always 5 positions long
this will be ~100 times faster than array_diff
$dups = array();
foreach(array_count_values($arr) as $val => $c)
if($c > 1) $dups[] = $val;
You can get the difference of the original array and a copy without duplicates using array_unique and array_diff_assoc:
array_diff_assoc($arr, array_unique($arr))
function array_dup($ar){
return array_unique(array_diff_assoc($ar,array_unique($ar)));
}
Should do the trick.
You can do like this:
function showDups($array)
{
$array_temp = array();
foreach($array as $val)
{
if (!in_array($val, $array_temp))
{
$array_temp[] = $val;
}
else
{
echo 'duplicate = ' . $val . '<br />';
}
}
}
$array = array(1,2,2,4,5);
showDups($array);
Output:
duplicate = 2
function returndup($array)
{
$results = array();
$duplicates = array();
foreach ($array as $item) {
if (in_array($item, $results)) {
$duplicates[] = $item;
}
$results[] = $item;
}
return $duplicates;
}
in addition to gumbo's answer:
function returndup($arr)
{
return array_diff_key($arr, array_unique($arr));
}
I did some tests and indeed #user187291's variant is the fastest. But, it turns out that #Gumbo's and #faebser's alternative are almost as fast, #faebser's being just slightly faster than #Gumbo's and sometimes even fastest of all.
Here's the code I used
$array = array(1, "hello", 1, "world", "hello");
$times = 1000000;
$start = microtime(true);
for ($i = 0; $i < $times; $i++) {
$dups = array();
foreach(array_count_values($array) as $val => $c)
if( $c > 1) $dups[] = $val;
}
$end = microtime(true);
echo 'variant 1 (user187291): ' . ($end - $start);
echo '<br><br><br>';
$start = microtime(true);
for ($i = 0; $i < $times; $i++)
$dups = array_unique(array_diff_assoc($array, array_unique($array)));
$end = microtime(true);
echo 'variant 2 (JAL): ' . ($end - $start);
echo '<br><br><br>';
$start = microtime(true);
for ($i = 0; $i < $times; $i++)
$dups = array_diff_assoc($array, array_unique($array));
$end = microtime(true);
echo 'variant 3 (Gumbo): ' . ($end - $start);
echo '<br><br><br>';
$start = microtime(true);
for ($i = 0; $i < $times; $i++)
$dups = array_diff_key($array, array_unique($array));
$end = microtime(true);
echo 'variant 4 (faebser): ' . ($end - $start);
echo '<br><br><br>';
I have found another way to return duplicates in an array
function printRepeating($arr, $size)
{
$i;
$j;
for($i = 0; $i < $size; $i++)
for($j = $i + 1; $j < $size; $j++)
if($arr[$i] == $arr[$j])
echo $arr[$i], " ";
}
printRepeating($array, sizeof($array,0);
If you need a solution that will work with an array of arrays (or any array values other than integers or strings) try this:
function return_dup( $arr ) {
$dups = array();
$temp = $arr;
foreach ( $arr as $key => $item ) {
unset( $temp[$key] );
if ( in_array( $item, $temp ) ) {
$dups[] = $item;
}
}
return $dups;
}
$arr = array(
array(
0 => 'A',
1 => 'B',
),
array(
0 => 'A',
1 => 'B',
),
array(
0 => 'C',
1 => 'D',
),
array(
0 => 'C',
1 => 'D',
),
array(
0 => 'E',
1 => 'F',
),
array(
0 => 'F',
1 => 'E',
),
array(
0 => 'Y',
1 => 'Z',
),
);
var_export( return_dup( $arr ) );
/*
array (
0 => array (
0 => 'A',
1 => 'B',
),
1 => array (
0 => 'C',
1 => 'D',
),
)
*/
As per your problem if you have duplicate values then you have to return those values. I write a function for this problem. If your array has duplicate values this function returns these values within the array otherwise it returns null values. Here is an example:
function containsDuplicate($array_values) {
$duplicates_values = [];
for($i = 0; $i < count($array_values); $i++){
for ($j=$i+1; $j <count($array_values) ; $j++) {
if ($array_values[$i] == $array_values[$j]) {
$duplicates_values[] = $array_values[$i];
}
}
}
if(count($duplicates_values) > 0){
return $duplicates_values;
}
}
$duplicate_array = array();
for($i=0;$i<count($array);$i++){
for($j=0;$j<count($array);$j++){
if($i != $j && $array[$i] == $array[$j]){
if(!in_array($array[$j], $duplicate_array)){
$duplicate_array[] = $array[$j];
}
}
}
}

Categories