Odd PHP behaviour when generating list of array values - php

I have a multidimensional PHP array of the following form:
Array
(
[0] => Array
(
[id] => 45
[date] => 2013-05-16
)
[1] => Array
(
[id] => 30
[date] => 2013-12-10
)
[2] => Array
(
[id] => 26
[date] => 2014-03-27
)
[3] => Array
(
[id] => 34
[date] => 2014-03-27
)
)
I am trying to generate a list of the [id] values, separated by commas, using the following PHP code:
foreach ($my_array as $key => $value) {
if ($key == 0) {
$id_list = $value[id];
}
if ($key !== 0 ) {
$id_list .= "," . $value[id];
}
}
I was hoping this would return
45,30,26,34
...but for some reason it returns
45,30,26,26
i.e. the penultimate ID is duplicated and the final ID is missed off. I have been staring at this for a while now but I can't see where I'm going wrong. Have I missed something obvious?

The better solution would be to not use those if() at all:
$ids = array();
foreach($arr as $val) {
$ids[] = $val['id'];
}
$id_str = implode(',', $ids);

Related

PHP replace multiple values from an array to another one

I want to insert the values from the first array inside the second array, where the key's name is [cost]:
$newcosts
Array (
[0] => 52.68
[1] => 7414.68
[2] => 2471.56
)
$mainarray
[0] => Array (
[id] => 2
[date] => 15.12.2020
[cost] => 60.00
)
[1] => Array (
[id] => 1
[date] => 22.12.2020
[cost] => 60.00
)
[2] => Array (
[id] => 3
[date] => 24.12.2020
[cost] => 22.00
)
I tried the following:
foreach ($mainarray as $key => $value) {
$values[] = $value['cost'];
$new_array[] = str_replace($values, $newcosts, $value);
}
for some reason, this is not showing the right data and sometime they get repeated. this is an example:
[0] => Array (
[id] => 2
[date] => 15.12.2020
[cost] => 52.68
)
[1] => Array (
[id] => 1
[date] => 22.12.2020
[cost] => 52.68
)
[2] => Array (
[id] => 3
[date] => 24.12.2020
[cost] => 2471.56
)
Hope someone could help me on that. Thank you very much!
Just use the mainarray's index to replace the $newcosts into the array.
foreach ($mainarray as $index => $subarray) {
$mainarray[$index]['cost'] = $newcosts[$index];
}
Because you will have an unused variable $subarray this way, it would be nicer to use a for loop:
for ($i = 0; $i < count($mainarray); $i++) {
$mainarray[$i]['cost'] = $newcosts[$i];
}
user foreach to get value of $newcosts and then
in loop replace value of price by id
in foreach loop you shuld replace value of $mainarray
foreach($newcosts as $itme => $value){
$mainarray [$itme ]['cost'] = $value;
}
Why are you using str_replace to replace float value ?
You can also index your array like this
for ($idx = 0; $idx <= count($mainarray); $idx++) {
$mainarray[$idx]['cost'] = $mainarray[$idx];
}
edit : same solution as above
A function-based equivalent to classic loops is to call array_walk() and modify the rows by reference. Using arrow function syntax (since PHP7.4) means you don't have to use use().
Code: (Demo)
array_walk(
$mainarray,
fn(&$row, $i) => $row['cost'] = $newcosts[$i]
);
var_export($mainarray);

PHP Loop through array with no index names

In PHP I have this structure of Array (some are empty, some not, some are multiple items):
Array
(
[0] => Array
(
)
[1] => Array
(
[0] => 16534
)
[2] => Array
(
)
[3] => Array
(
[0] => 16532
[1] => 16533
)
[4] => Array
(
)
[5] => Array
(
[0] => 14869
)
}
I want to loop through this array, so as the result I get only the numbers (all of them).
I tried it this way:
foreach ($myarray as $item) {
echo '<pre>' . print_r($item) . '</pre>';
// $result[] = $this->myMethod($item);
}
So in foreach I want to use all the items from array in my method.
However when I echo the $item in the loop, I have something like this:
Array ( )
Array ( [0] => 16534 )
Array ( )
Array ( [0] => 16532 [1] => 16533 )
Array ( )
Array ( [0] => 14869 )
So still arrays (also the empty ones), and not numbers.
Can you please help with this?
UPDATE: I just noticed, some of the arrays looks like this:
[6] => Array
(
[0] => Array
(
[id] => 269
[hours] => 21.0
)
)
[7] => Array
(
[0] => Array
(
[0] => Array
(
[id] => 2
[hours] => 12.0
)
[1] => Array
(
[id] => 7
[hours] => 24.0
)
)
[1] => Array
(
[0] => Array
(
[id] => 2
[hours] => 5.0
)
[1] => Array
(
[id] => 7
[hours] => 0.583
)
)
)
but here the solution works not.
This one seems working but it is now brutal foreach in foreach solution:
foreach ($myarray as $item2) {
foreach ($item2 as $key2 => $val2) {
if (isset($val2)) {
foreach ($val2 as $key4 => $val4) {
echo $val4['id'].',';
}
}
}
}
Just merge the array which will also remove the empties:
foreach(array_merge(...$myarray) as $item) {
// echo '<pre>' . print_r($item) . '</pre>';
$result[] = $this->myMethod($item);
}
This will also work and may be faster:
$result = array_map([$this, 'myMethod'], array_merge(...$myarray));
If you have an old PHP version you'll have to use array() instead of [] and:
call_user_func_array('array_merge', $myarray)
You are only looping through the main array.That's the reason why you are getting an array when you are printing the result set.(because those values are stored in sub arrays and you are not looping them.)
And to remove the sub arrays with empty values I'll use isset() so that you will get only the values.
Change your code into this.
foreach ($myarray as $item) {
foreach($item as $key=>$val){
if(isset($val){
$values[] = $val;
// $result[] = $this->myMethod($values);
}
}
}

PHP and 2 multidimensional array compare based on two key values

I have two multidimensional arrays like this:
$original = Array (
[0] => Array
(
[time] => 1364690340
[memberid] => 90
[type] => single
)
[1] => Array
(
[time] => 1364690341
[memberid] => 92
[type] => fixed
)
[2] => Array
(
[time] => 1364690342
[memberid] => 96
[type] => single
)
)
and second one like this
$new = Array (
[0] => Array
(
[time] => 1364825750
[memberid] => 90
[type] => single
)
[1] => Array
(
[time] => 1364825751
[memberid] => 92
[type] => single
)
[2] => Array
(
[time] => 1364825752
[memberid] => 96
[type] => single
)
[3] => Array
(
[time] => 1364825753
[memberid] => 111
[type] => single
)
)
My problem is: I want to search $original array for matches based on memberid and type keys and if memberid and type ARE NOT the same -> I want to remove that array from $original array. So in this case I want to keep [0] Array and [2] Array as in $new array I have same memberid and same type as in original, but I would want to remove [1] Array as memberid is the same, but type is different. So my final $original array will look like this:
$original = Array (
[0] => Array
(
[time] => 1364690340
[memberid] => 90
[type] => single
)
[1] => Array
(
[time] => 1364690342
[memberid] => 96
[type] => single
)
)
Here you go, just tested it and it works as expected.
// Presuming your two arrays are still called $new & $original
$original = array(); // your data
$new = array(); // your data
$newArray = array();
foreach($original AS $key => $val){
$newArray[$val['memberid'] . '-' . $val['type']] = $val;
}
$original = array();
foreach($new AS $key => $val){
if(isset($newArray[$val['memberid'] . '-' . $val['type']])){
$original[] = $newArray[$val['memberid'] . '-' . $val['type']];
}
}
print_r($original);
Without making any assumptions about your data, here's an inefficient solution, O(m * n) if m and n are the lengths of your arrays:
$new_original = array();
foreach ($original as $elem) {
// let's see if $new has something with the same type and memberid
foreach ($new as $candidate) {
if ($candidate['type'] == $elem['type'] &&
$candidate['memberid'] == $elem['memberid']) {
// it does! let's keep $elem
$new_original[] = $elem;
}
}
}
// reassign it to $original if desired
$original = $new_original;
However, it would be much cooler to do more efficient lookups. For example, if we can assume there is at most one element with a given memberid in $new:
// turn $new into a map
$new_as_map = array();
foreach ($new as $candidate) {
$new_as_map[$candidate['memberid']] = $candidate;
}
$new_original = array();
foreach ($original as $elem) {
if (isset($new_as_map[$elem['memberid']])) {
$candidate = $new_as_map[$elem['memberid']];
if ($candidate['type'] == $elem['type']) {
$new_original[] = $elem;
}
}
}
// reassign it to $original if desired
$original = $new_original;

Create new array from another

i have an array:
Array
(
[users] => Array
(
[101] => Array
(
[odata] => Array
(
[0] => 2
[1] => 1
[2] => 1
[3] => 1
)
)
[200] => Array
(
[odata] => Array
(
[0] => 2
[1] => 1
[2] => 1
[3] => 0
)
)
)
[rjad] => Array
(
[2] => Array
(
[0] => red
[1] => blue
[2] => green
)
)
)
in this array [rjad] key = [odata] key, and [odata] value = second key in [rjad].
What i want is to create new array from old one with user ids values in second array:
like this:
[rjad] => Array
(
[2] => Array
(
[0] => red
[1] => Array
(
[blue] => Array
(
[0] => 101
[1] => 200
)
[2] => green
)
)
Struggling already 3 hours with no success. Any ideas how to get it are very wellcome.
Image do explain relatinships
http://imageshack.us/photo/my-images/818/phparray.jpg/
I'd seriously rethink your structure, but here's a working (if ugly) solution
foreach ($users as $userId => $user) {
foreach ($user['odata'] as $key => $value) {
if (isset($rjad[$key][$value])) {
if (!is_array($rjad[$key][$value])) {
$colour = $rjad[$key][$value];
$rjad[$key][$value] = array();
$rjad[$key][$value][$colour] = array();
} else {
reset($rjad[$key][$value]);
$colour = key($rjad[$key][$value]);
}
$rjad[$key][$value][$colour][] = $userId;
}
}
}
Working demo -> http://codepad.viper-7.com/IEcpvU
Based on comments seems you may want a separate array, which is easily solved
// copy the array and act on it instead of directly on $rjad
$result = $rjad;
foreach ($users as $userId => $user) {
foreach ($user['odata'] as $key => $value) {
if (isset($result[$key][$value])) {
if (!is_array($result[$key][$value])) {
$colour = $result[$key][$value];
$result[$key][$value] = array();
$result[$key][$value][$colour] = array();
} else {
reset($result[$key][$value]);
$colour = key($result[$key][$value]);
}
$result[$key][$value][$colour][] = $userId;
}
}
}
Your question isn't entirely clear - what is the relationship between rjad...blue and those user accounts from the other array? Is item 0 in the odata arrays the default colour?

Remove item from multidimensional array php

Here is the array:
[cart] => Array
(
[ProductId] => Array
(
[0] => P121100001
[1] => P121100002
)
[SellerId] => Array
(
[0] => S12110001
[1] => S12110001
)
[SpecifyId] => Array
(
[0] => 1
[1] => 2
)
[Quantity] => Array
(
[0] => 1
[1] => 1
)
[Price] => Array
(
[0] => 12
[1] => 29
)
[TotalPrice] => 41
)
I have the ProductId and I want to remove all the other items matching P121100002's key.
Is there an easy way to do this I can't can seem to come up with one?
You can loop through the full array and use unset() to, well, "unset" the specified index:
$index = array_search($cart['ProductId'], 'P121100002');
if ($index !== false) {
foreach ($cart as $key => $arr) {
unset($cart[$key][$index]);
}
}
The slight caveat to this approach is that it may disrupt your index orders. For instance, say you have:
[ProductId] => Array (
[0] => P121100001
[1] => P121100002
[2] => P121100003
)
And you want to remove P121100002, which has a corresponding index of 1. Using unset($cart['ProductId'][1]) will cause your array's to become:
[ProductId] => Array (
[0] => P121100001
[2] => P121100003
)
This may be something to remain concerned with if you're going to use a for loop to iterate through in the future. If it is, you can use array_values() to "reset" the indexes in the unset() loop from above:
foreach ($cart as $key => $arr) {
unset($cart[$key][$index]);
$cart[$key] = array_values($cart[$key]);
}
foreach($yourArray['ProductId'] as $key => $value) {
if ($value == $productIdToRemove) {
foreach($yourArray as $deleteKey => $deleteValue) {
unset($yourArray[$deleteKey][$key]);
}
break;
}
}
Use array_key_exists along with the unset() function

Categories