PHP 'list' working on non-numerical arrays? - php

$colors = array(
'r' => 'a',
'g' => 'b',
'b' => 'c'
);
list($v, $k) = each($colors);
echo $v . " " . $k
Now the above prints r a
which I'm surprise since I thought the 'list' construct only works for numerical array. Why does it work?

Yes you are right list() only works on numerical arrays and assumes the numerical indices start at 0. but he reason why your code is working its because of each.
each traverse an array therefore converted the keys to numerical example if you run the following :
$foo = array("r"=>"a");
$bar = each($foo);
echo "<pre>";
print_r($bar);
Output
Array
(
[1] => a
[value] => a
[0] => r
[key] => r
)
You can use that array('r' => 'a'); has been converted to array(0 => 'r', 1 => 'a'); therefore you can now use list since they now have numerical keys
FROM PHP DOC
each Return the current key and value pair from an array and advance the array cursor.
each Returns the current key and value pair from the array array. This pair is returned in a four-element array, with the keys 0, 1, key, and value. Elements 0 and key contain the key name of the array element, and 1 and value contain the data.
Also
each() is typically used in conjunction with list() to traverse an array, here's an example:

Read the manual closer for each():
Returns the current key and value pair from the array array. This pair is returned in a four-element array, with the keys 0, 1, key, and value. Elements 0 and key contain the key name of the array element, and 1 and value contain the data.
So when you do each($colors), the following is returned:
array(0 => 'r' => 1 => 'a', 'key' => 'r', 'value' => 'a')
Then list() takes the values for 0 and 1 and assigns them to $v and $k respectively. Make sense?

Related

PHP array_diff_key() is empty but should not

I query a series of tables in order to print these, and I want to print all keys of each table even if the values are empty, but a specific set of keys which are the same for each table shall not be printed.
My query and fetch of the result in an array for one table:
$stmt = $db_conn->prepare("SELECT * FROM table;");
$stmt->execute();
$array = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt->closeCursor();
var_export($array);returns:
array ( 0 => array ( 'a' => '1', 'b' => '2018-12-21', 'c' => '', 'd' => '', ), )
I prepared a list of bad keys in an array:
var_export($bad_keys);returns:
array ( 0 => array ( 'a' => '1', 'b' => '2019-01-05', ), )
For each table I want to exclude the bad keys {a, b} from the query result in $array by use of array_diff_key():
$array_new = array_diff_key($array, $bad_keys);
var_dump($array_new); returns empty:
array(0) { }.
$array_new should have the keys {'c', 'd'} but it has not. I don't see a mistake in my code. Please help.
array_diff_key is used to compute the difference between the keys of two or more arrays, i.e. a new array with all key/value pairs of the first array argument having keys not existing in any other array argument's keys are returned.
In your code, you try to compare the keys of your first array with an array of values (i.e. your $bad_keys, actually having numbered indexes), not the keys of the $bad_keys array. This is not how array_diff_key works.
Be sure to check out the reference at: http://php.net/manual/en/function.array-diff-key.php
One method giving you only the keys you are looking for as an array:
Just create a new array of the keys of the first array as values and then use array_diff to compare it with your $bad_keys.
To get the key/value pairs you can use this one (as Quasimodo's Clone suggested):
array_diff_key($array, array_flip($bad_keys))
UPDATE: The keys in the first array are also not at the same level as the keys in the $bad_array.
My mistake: In array_diff_key() I compared two multidimensional arrays without writing the index [0] for each array to be compared.
Solution: I added the index [0] to each array to be compared, and additionally I created an array from the result of array_diff_key()
$array = array( 0 =>
array(
'a' => '',
'b' => '',
'c' => '',
'd' => '',
),
);
$bad_keys = array( 0 =>
array(
'a' => '',
'b' => '',
),
);
$array_new = array( array_diff_key( $array[0], $bad_keys[0] ));
var_export( $array_new );
now returns the desired result:
array( 0 =>
array(
'c' => '',
'd' => '',
),
);

PHP: Ignore key and extract value of an array

I have a function that returns an array where the value is an array like below: I want to ignore the key and extract the value directly. How can I do this without a for loop? The returned function only has one key but the key (2 in this case) can be a variable
Array ( [2] => Array ( [productID] => 1 [offerid]=>1)
Expected result:
Array ( [productID] => 1 [offerid]=>1)
There're at least 3 ways of doing this:
Use current function, but be sure that array pointer is in the beginning of your array:
$array = Array (2 => Array ( 'productID' => 1, 'offerid' => 1));
$cur = current($array);
var_dump($cur, $cur['offerid']);
Next is array_values function, which will give you array of values with numeric keys, starting with 0
$array = Array ( 2 => Array ( 'productID' => 1, 'offerid' => 1));
$av = array_values($array);
var_dump($av[0], $av[0]['offerid']);
And third option is use array_shift, this function will return first element of array, but be careful as it reduces the original array:
$array = Array ( 2 => Array ( 'productID' => 1, 'offerid' => 1));
$first = array_shift($array);
var_dump($first, $first['offerid']);
If you want to get the current value of an array, you can use current() assuming the array pointer is in the correct position. If there is only one value, then this should work fine.
http://php.net/manual/en/function.current.php
I think Devon's answer will work for you , but if not your can try
$arr = array_column($arr, $arr[2]);
if you need always the second index of your master array, if you need all index use
array_map(),
something like array_map('array_map', $arr); should work.

Couldn't use integer as a key in associative array PHP

I want to use an integer as key in an associative array. I tried using settype() method to convert it to string and then merge it with an existing associative array
Here is the code:
$Xcenter = 325;
$Ycenter = 59.8;
$Xcenter = strval($XCenter);
$existing_array = array('a'=>'b', 'b'=>'c');
$new_array = array($XCenter=>$YCenter);
$result = array_merge($existing_array, $new_array);
print_r($result);
Current Output:
Array ( [a] => b [b] => c [0] => 59.8 )
Expected Output:
Array ( [a] => b [b] => c [325] => 59.8 )
For some reason it is not converting integer to string. But this is working perfectly fine for float values like the one below:
Array ( [a] => b [b] => c [148.33333333333] => 59.8 )
From the manual for array_merge:
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.
If you want to just set a key to a specific value, you don't need to merge, you can just set it like $array[123] = $foo. Or do a union with $array1 + $array2. But just an FYI, a union will not re-index numeric keys and it will not overwrite previous values. So you typically have to reverse the arguments that you would normally pass to array_merge. So array_merge($a1, $a2) is pretty much the same as $a2 + $a1 without the re-indexed numeric keys.

Accessing an associative array by integer index in PHP

I want to set the value of an associative array using the array index of the key/value pair. For example:
$my_arr = array( "bling" => "some bling", "bling2" => "lots O bling" );
$my_arr[1] = "not so much bling"; // Would change the value with key bling2.
How can this be accomplish this without using the key string?
Use array_keys.
$keys = array_keys($my_arr);
$my_arr[$keys[1]] = "not so much bling";
There is no correlation between numeric and associative index keys.
When you say you want to set the value of an associative array using the array index of the key/value, then you have to use the given key, setting $array[1] is not the same as setting $array['foo'].
Consider this array
print_r( array('foo', 'foo' => 'bar', 'baz', 'some' => 'value') );
This will give
Array
(
[0] => foo
[foo] => bar
[1] => baz
[some] => value
)
The foo is the second element in the array. That's the offset, but it has nothing to do with the index 1. As you can see, in that array above, index 1 is associated with baz. It is wrong to assume that just because foo is the first associative key it has anything to do with the actual numeric key 1. Just like some does not correlate to 2.
Likewise, for a mixed array like shown above, the solution with array_keys suggested elsewhere on this site will not work, because
print_r( array_keys(array('foo', 'foo' => 'bar', 'baz', 'some' => 'value')) );
will give
Array
(
[0] => 0
[1] => foo
[2] => 1
[3] => some
)
So when you do $array[$keys[1]] you are really doing $array['foo']. But if you wanted to access the second associative value in that array ('some'), you cannot do $array[$keys[2]] because that would evaluate to $array[1] and that's baz.
The Offset of an element is completely unrelated to it's key or value
print_r(
array(
100 => 'foo',
'foo' => 'bar',
50 => 'baz',
'some' => 'value'
)
);
really means
Array
( //key value offset/position
[100] => foo // 0
[foo] => bar // 1
[50] => baz // 2
[some] => value // 3
)
which means the element at offset 0 is foo although it's key is 100. If you want to extract elements from an array by offset, you have to use
$third = array_splice($array, 2, 1);
echo $third[0]; // baz
This would create an array holding only the element at the third position.
Or you could use an ArrayIterator. The ArrayIterator implements a Seekable interface that lets you seek to a specific position/offset in the array and then fetch that:
$iterator = new ArrayIterator($array);
$iterator->seek(3);
echo $iterator->current(); // value
Whilst array_keys() allows access to the nth key, array_values will give you the nth value.
<?php
$array = [
0 => 'Zero',
'1' => 'One',
'Two' => 'Two',
];
echo array_values($array)[2];
?>
will output 'Two'.
Is there an advantage of one over the other? Well, the only minor one I can see is the number of array accesses.
With array_keys() you need to 3.
Get the keys from the data array.
Get the nth key from the list of keys.
Get the value using the nth key from the data array.
With array_values(), you only need 2.
Get the values from the data array.
Get the nth value from the list of values.
But, on the other hand, keys are normally smaller and the data could be hugely nested, so, on balance, using the array_keys() is probably safer.
If the array is large, both array_keys and array_values will be wasteful since they will allocate a new array the same size as the original, just to get the nth key (or value).
array_slice accepts an integer offset and works on associative arrays. You can use it to get (and set) the nth key in constant time.
// This will at most allocate 2 temporary arrays of 1 element each
$key = array_keys(array_slice($array, $n, 1, true))[0];
$array[$key] = $value;
Try this. It works for you.
$result= array_values($my_arr); // Array with indexes you need
Another possibility is to convert it to a normal array:
$arraybuff = implode("~~~",$my_arr);
$my_arr = explode("~~~",$arraybuff);
Where "~~~" is a delimiter that wont occur in your data.
Now you can access the array using numerical indexes equal to the offsets.
If you still need to retain your associative array, just assign it to a different variable.

how to use array_push when pushing both key and value in PHP

I have an empty array. I am able to push values using
array_push($list, item[0]);
But how do I push both key and value.
array_push($list[$key], $item[0])
this does not work.
$list['key']=$item[0];
should work.
Note: If you use array_push() to add one element to the array it's better to use $array[] = because in that way there is no overhead of calling a function.
If you want to maintain the key => value pairs you could use array_merge function.
$arr1 = array('apple' => 'fruit', 'banana' => 'fruit');
$arr2 = array('turnip' => 'vegetable', 'mushroom' => 'other');
$newArray = array_merge($arr1,$arr2)
This will return:
Array
(
[apple] => fruit
[banana] => fruit
[turnip] => vegetable
[mushroom] => other
)
But if two keys are the same in two arrays the one in the first array will be overwritten by the value in the second.

Categories