I have two arrays (this is an JSON array from PHP)
one
"result1": [
{
"driverId": "3",
"latitude": "23.752182",
"longitude": "90.377730",
"distance": "0.00011211999971692422",
"EstTime": 137
},
{
"driverId": "4",
"latitude": "23.75182",
"longitude": "90.3730",
"distance": "0.000171692422",
"EstTime": 111
}
]
Two
"result2": [
{
"driverId": "3"
}
]
I want to compare these arrays. if any result1 item driverID matches any item of result2 then skip that item from result1
You can do this in two stages.
First gather the driverIds to exclude using array_map
$exclude = array_map(
function($v) {
return $v['driverId'];
},
$json['result2']
);
Then use array_filter to filter out those elements you do not want:
$result = array_filter(
$json['result1'],
function($a) use ($exclude) {
return !in_array($a['driverId'], $exclude);
}
);
I have tested this with the following code. If you have separate arrays, just supply them independently above instead of using $json['result1'].
$a = <<<JSON
{
"result1": [
{
"driverId": "3",
"latitude": "23.752182",
"longitude": "90.377730",
"distance": "0.00011211999971692422",
"EstTime": 137
},
{
"driverId": "4",
"latitude": "23.75182",
"longitude": "90.3730",
"distance": "0.000171692422",
"EstTime": 111
}
],
"result2": [
{
"driverId": "3"
}
]
}
JSON;
$json = json_decode($a, true);
Try the following. In this answer I am assuming that you have already applied json_decode() and extracted $result1 and $result2 into PHP arrays.
Further to your last comment, code edited to work in version 5.2
<?php
// associative array of result1
$result1 = array(
array(
'driverId' => '3',
'latitude' => '23.752182',
'longitude' => '90.377730',
'distance' => '0.00011211999971692422',
'EstTime' => 137
),
array(
'driverId' => '4',
'latitude' => '23.75182',
'longitude' => '90.3730',
'distance' => '0.000171692422',
'EstTime' => 111
)
);
// associative array of result2
$result2 = array(
array(
'driverId' => '3'
)
);
// first, let's get a list of ids that we want to exclude
// run array map over the result2 and return the ids - this
// creates an array of "exclusion" ids. Note you could use
// foreach here also.
function pluckResultIds($result) {
return $result['driverId'];
}
$excludeIds = array_map('pluckResultIds', $result2);
var_dump($excludeIds); // result: array(3)
// next let's use array_filter to run over result1. for each
// entry in result1 - we check if the current driverId is in
// the exclusion array - if it is *not* we return the current
// this creates a new array $filtered containing only the
// filtered elements that do not match
$filtered = array();
foreach ($result1 as $result) {
$id = $result['driverId'];
if (!in_array($id, $excludeIds)) {
$filtered[] = $result;
}
};
var_dump($filtered);
Yields:
array (size=1)
1 =>
array (size=5)
'driverId' => string '4' (length=1)
'latitude' => string '23.75182' (length=8)
'longitude' => string '90.3730' (length=7)
'distance' => string '0.000171692422' (length=14)
'EstTime' => int 111
Hope this helps! :)
Related
im currently trying to update an array with values from another one.
Basically there is a form where you can update data for an object, the form sends a json array like so:
{
"name": "Test2",
"address": "Adresas 2",
"object_id": "44",
"job_id": [
"31",
"33"
],
"amount": [
"500",
"500"
]
}
My goal is to update another array that is being fetched from the database with values of job_idd and amount.
The array from database looks like so:
{
"jobs": [
{
"id": "31",
"amount": "500",
"have": 250
},
{
"id": "33",
"amount": "500",
"have": 0
}
]
}
I need to update the second array values "amount" with the posted values from the first array "amount", but so that the second array still has the original "have" values
I tried using nested foreach method:
$object_id = $_POST['object_id'];
$data = json_encode($_POST);
$json = json_decode($data, true);
$i = 0;
foreach($json['job_id'] as $item) {
$job_id = $item;
$query33 = "SELECT * FROM `objektai` WHERE id='$object_id'";
$result33 = mysqli_query($conn, $query33) or die(mysqli_error($conn));
while($row2 = mysqli_fetch_array($result33)){
$job_info = $row2['info'];
}
$json_22 = json_decode($job_info, true);
foreach ($json_22['jobs'] as $key2 => $entry2) {
$have = $json_22['jobs'][$key2]['have'];
}
$result["jobs"][] = array(
'id' => $job_id,
'kiekis' => $json['amount'][$i],
'turima' => $have,
);
$i++;
}
Usinng the example above the foreach prints the values 2 times and my updated json "have"
has a value of 0, the "amount" entries are updated correctly
Thanks in advance for you help!
UPDATE
adding var_export($_POST):
array ( 'name' => 'Test2',
'address' => 'Adresas 2',
'object_id' => '44',
'job_idd' => array (
0 => '31',
1 => '33',
),
'darbo_kiekis' => array (
0 => '500',
1 => '500',
),
)
When you're looping through the array from the database, you need to compare the id value with $obj_id.
I've also shown below how to use a prepared statement to prevent SQL injection.
I've removed lots of unnecessary code:
No need to convert $_POST to/from JSON.
Use $i => in the foreach loop to get the array index.
You don't need a while loop when processing the query results if it only returns one row.
You don't need $key2, you can just use $entry2.
$object_id = $_POST['object_id'];
$query33 = "SELECT * FROM `objektai` WHERE id = ?";
$stmt33 = $conn->prepare($query33);
$stmt33->bind_param('i', $job_id);
foreach($_POST['job_id'] as $i => $job_id) {
$stmt33->execute();
$result33 = $stmt33->get_result();
$row2 = $result33->fetch_assoc();
$job_info = $row2['info'];
$json_22 = json_decode($job_info, true);
foreach ($json_22['jobs'] as $entry2) {
if ($entry2['id'] == $job_id) {
$result["jobs"][] = array(
'id' => $job_id,
'kiekis' => $json['amount'][$i],
'turima' => $entry2['have']
);
}
}
}
I have two arrays.
The first one is about exchange-rate and the display in my console is like this :
{
"exchange_rate": [
{
"id": "978",
"start_dateTime": "2021-08-01 07:35:02",
"target_value": "1.00000",
"currency_value_euro": "0.84097",
"currency_value_dollar_us": "1.00000",
"id_currency": "1",
"currency": "Dollar am\u00e9ricain",
"currency_symbol": "$US"
},
{
"id": "980",
"start_dateTime": "2021-08-01 07:35:02",
"target_value": "1.00000",
"currency_value_euro": "1.17454",
"currency_value_dollar_us": "0.71600",
"id_currency": "2",
"currency": "Livre sterling",
"currency_symbol": "\u00a3"
}
]
}
These data came from the database and I can display it by choosing particular dates with jQuery.
The second array contains only id_currency which in my console is like this : Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5
On my website, I want to be able to display specific exchange rate by specific currency and dates.
And here my problem appears, I can't find the way to loop on the first array, and loop again inside, on the second array and compare both like if first array has id_currency 1 and second array has id_currency 1 then display the complete line from first array.
I've tried several things but nothing works, at last i've tried this :
foreach ($res as $row){
$idBDD = $row['id_currency'];
$symbolBDD = $row['currency_symbol'];
echo $idBDD;
echo $symbolBDD;
//var_dump($row);
/*foreach ($arr as $line){
$idCheckbox = $line;
echo $idCheckbox;
}
if ($idBDD == $idCheckbox){
echo 'fine';
}
*/
}
I'll be grateful for your help
You need to access the array with $res["exchange_rate"] and loop through it then.
<?php
$res = [
"exchange_rate" => [
[
"id" => "978",
"start_dateTime" => "2021-08-01 07:35:02",
"target_value" => "1.00000",
"currency_value_euro" => "0.84097",
"currency_value_dollar_us" => "1.00000",
"id_currency" => "1",
"currency" => "Dollar américain",
"currency_symbol" => "\$US"
],
[
"id" => "980",
"start_dateTime" => "2021-08-01 07:35:02",
"target_value" => "1.00000",
"currency_value_euro" => "1.17454",
"currency_value_dollar_us" => "0.71600",
"id_currency" => "2",
"currency" => "Livre sterling",
"currency_symbol" => "£"
]
]
];
$output = null;
foreach ($res["exchange_rate"] as $row) {
if (!isset($output)) {
$output = $row;
}
$output = array_intersect_assoc($output, $row);
}
var_dump($output);
I think you could do it like this, of course if you're inside the loop, you won't need to put indices.
read more array_diff()
https://www.php.net/manual/pt_BR/function.array-diff.php
$array = [
"exchange_rate" => [
[
"id" => "978",
"start_dateTime" => "2021-08-01 07:35:02",
"target_value"=> "1.00000",
"currency_value_euro"=> "0.84097",
"currency_value_dollar_us"=> "1.00000",
"id_currency"=> "1",
"currency"=> "Dollar am\u00e9ricain",
"currency_symbol" => "US"
],[
"id"=> "980",
"start_dateTime"=> "2021-08-01 07=> 35=> 02",
"target_value"=> "1.00000",
"currency_value_euro"=> "1.17454",
"currency_value_dollar_us"=> "0.71600",
"id_currency"=> "2",
"currency"=> "Livre sterling",
"currency_symbol"=> "\u00a3"
]
]
];
$array1 = $array['exchange_rate'][0];
$array2 = $array['exchange_rate'][1];
$result = array_diff( $array1, $array2);
var_dump($result);
I have this array:
0 => array:3 [
"product_id" => "1138"
"product_image" => "/resources/medias/shop/products/shop-6500720--1.png"
"product_sku" => "6500722"
]
1 => array:3 [
"product_id" => "1144"
"product_image" => "/resources/medias/shop/products/shop-6501041--1.png"
"product_sku" => "6501046"
]
2 => array:3 [
"product_id" => "113"
"product_image" => "/resources/medias/shop/products/shop-6294909--1.png"
"product_sku" => "6294915"
]
What I am looking for is a way to get a multiple array with only required columns (array_column is not a option, since it's give me only 1 column).
What I have done
function colsFromArray($array, $keys)
{
return array_map(function ($el) use ($keys) {
return array_map(function ($c) use ($el) {
return $el[$c];
}, $keys);
}, $array);
}
$array = array(
[
"product_id" => "1138",
"product_image" => "/resources/medias/shop/products/shop-6500720--1.png",
"product_sku" => "6500722"
],
[
"product_id" => "1144",
"product_image" => "/resources/medias/shop/products/shop-6501041--1.png",
"product_sku" => "6501046"
],
[
"product_id" => "113",
"product_image" => "/resources/medias/shop/products/shop-6294909--1.png",
"product_sku" => "6294915"
]
);
colsFromArray($array, array("product_id", "product_sku"));
//0 => array:3 [
// "product_id" => "1138"
// "product_sku" => "6500722"
// ]
//1 => array:3 [
// "product_id" => "1144"
// "product_sku" => "6501046"
// ]
//2 => array:3 [
// "product_id" => "113"
// "product_sku" => "6294915"
//]
The problem is that it seems too laggy, since it iterates twice over this.
Is there any way to get multiple columns without this workaround?
I'm using PHP5.6
If you need two columns from an array where one is SKU (which generally is unique) then you can use array_column with the third parameter.
$new = array_column($arr, "product_id", "product_sku");
This will return a flat array with the SKU as the key and ID as value making the array easy to work with also.
Output:
array(3) {
[6500722]=>
string(4) "1138"
[6501046]=>
string(4) "1144"
[6294915]=>
string(3) "113"
}
https://3v4l.org/UDGiO
I think the bigger issue is you lose the keys
Original Code
array (
0 =>
array (
0 => '1138',
1 => '6500722',
),
1 =>
array (
0 => '1144',
1 => '6501046',
),
2 =>
array (
0 => '113',
1 => '6294915',
);
You can use a simple foreach instead of the second array_map:
function colsFromArray(array $array, $keys)
{
if (!is_array($keys)) $keys = [$keys];
return array_map(function ($el) use ($keys) {
$o = [];
foreach($keys as $key){
// if(isset($el[$key]))$o[$key] = $el[$key]; //you can do it this way if you don't want to set a default for missing keys.
$o[$key] = isset($el[$key])?$el[$key]:false;
}
return $o;
}, $array);
}
Output
array (
0 =>
array (
'product_id' => '1138',
'product_sku' => '6500722',
),
1 =>
array (
'product_id' => '1144',
'product_sku' => '6501046',
),
2 =>
array (
'product_id' => '113',
'product_sku' => '6294915',
),
)
Sandbox
the problem is that it seems too laggy, since it iterates twice over this.
There is no real way to not iterate over it 2 times, but you probably don't want to throw away the keys either.
That said you can recursively unset the items you don't want.
function colsFromArray(array &$array, $keys)
{
if (!is_array($keys)) $keys = [$keys];
foreach ($array as $key => &$value) {
if (is_array($value)) {
colsFromArray($value, $keys); //recursive
}else if(!in_array($key, $keys)){
unset($array[$key]);
}
}
}
colsFromArray($array, array("product_id", "product_sku"));
var_export($array);
Same output as before
This is easier to do by reference. Rather or not that is faster you'll have to test the 2 and see.
Sandbox
As a final note you shouldn't assume the key will exist or that keys will be an array unless you type cast it as an array.
You could also do it with array filter
function colsFromArray(array $array, $keys)
{
if (!is_array($keys)) $keys = [$keys];
$filter = function($k) use ($keys){
return in_array($k,$keys);
};
return array_map(function ($el) use ($keys,$filter) {
return array_filter($el, $filter, ARRAY_FILTER_USE_KEY );
}, $array);
}
There is some small performance benefit to declaring the function for filtering outside of the loop (array_map).
Sandbox
If you do not want to change your original array and want your desired output
Use array_insersect_key function to get your desired output as following
$array = array(
[
"product_id" => "1138",
"product_image" => "/resources/medias/shop/products/shop-6500720--1.png",
"product_sku" => "6500722"
],
[
"product_id" => "1144",
"product_image" => "/resources/medias/shop/products/shop-6501041--1.png",
"product_sku" => "6501046"
],
[
"product_id" => "113",
"product_image" => "/resources/medias/shop/products/shop-6294909--1.png",
"product_sku" => "6294915"
]
);
$keys = array("product_id"=>1, "product_sku"=>2);
$filteredArray = array_map(function($a) use($keys){
return array_intersect_key($a,$keys);
}, $array);
print_r($filteredArray);
I refactored the elegant approach from #Chayan into a function so it can be used like array_column(). Keys to be filtered can now be presented as a simple array.
Btw this is most likely also the fastest approach, since it uses build-in functions for most of the heavy lifting.
function array_columns(array $arr, array $keysSelect)
{
$keys = array_flip($keysSelect);
return array_map(
function($a) use($keys) {
return array_intersect_key($a,$keys);
},
$arr
);
}
$arr = [
[
"product_id" => "1138",
"product_image" => "/resources/medias/shop/products/shop-6500720--1.png",
"product_sku" => "6500722"
],
[
"product_id" => "1144",
"product_image" => "/resources/medias/shop/products/shop-6501041--1.png",
"product_sku" => "6501046"
],
[
"product_id" => "113",
"product_image" => "/resources/medias/shop/products/shop-6294909--1.png",
"product_sku" => "6294915"
]
];
$keysSelect = ["product_id" , "product_sku"];
$filteredArray = array_columns($arr, $keysSelect);
var_dump($filteredArray);
If I understand your question correctly, you could try a traditional foreach - it might be a little faster.
function colsFromArray($array, $filterKeys) {
$newArr = [];
foreach($array as $val) {
$element = [];
foreach($filterKeys as $filterKey) {
$element[$filterKey] = $val[$filterKey];
}
$newArr[] = $element;
}
}
(Not tested)
The problem is that it seems too laggy, since it iterates twice over this
Your original code isn't iterating twice over the same array. You won't be able to get around iterating over the main array and then the filterKeys array if you want to have an array where each element is another array of elements with keys from the filterKeys array.
This is a refactored function based on Chayan's with added renaming of selected columns:
/** Function - array_columns Selects columns from multidimantional array and renames columns as required
*
* #param array $arr, array $selectColRenameKeys
* example: (NewName1->colNameneeded1,NewName2->colNameneeded2,ect...)
* #return array
* #access public
*
*/
private function array_columns( $arr,$selectColRenameKeys) {
$keys = array_flip($selectColRenameKeys);
$filteredArray = array_map(function($a) use($keys){
$data = array_intersect_key($a,$keys);
$rename_arr= array();
foreach ($data as $colname => $value){
$r_arr[$keys[$colname]]= $value ;
}
return $r_arr;
}, $arr);
return $filteredArray;
}
An added feature to the array_columns function that eventually traces back to Chayan's answer, this time extended from Joseph Mangion's function.
I occasionally have long lists of the selected columns where I want to preserve the keys and don't necessarily want to follow the cumbersome ['orignal_field_name'] => ['original_field_name'] format for a great number of fields.
This version preserves the original key for each field by default unless a new key is specified.
// See answer from Joseph Mangion: https://stackoverflow.com/questions/52706383/php-get-multiple-columns-from-array
/** Function - array_columns Selects columns from multidimensional array and renames columns as required
*
* #param array $in_array, array $select_columns_rename_keys
* example of $select_columns_rename_keys:
* ['new_column_name1' => 'original_column_name1', 'original_column_name2', 'original_column_name3', 'new_column_name4' => 'original_column_name4', ...]
* This will use the original keys for columns 2 and 3 and rename columns 1 and 4
* #return array
* #access public
*
*/
public function array_columns($in_array, $select_columns_rename_keys) {
foreach ($select_columns_rename_keys as $k => $v)
if (is_int($k)) {
$select_columns_rename_keys[$v] = $v;
unset($select_columns_rename_keys[$k]);
}
$keys = array_flip($select_columns_rename_keys);
$filtered_array =
array_map(function($a) use($keys) {
$data = array_intersect_key($a, $keys);
$return_array = [];
foreach ($data as $column_name => $value) $return_array[$keys[$column_name]] = $value;
return $return_array;
}, $in_array);
return $filtered_array;
}
I would like in php to stop duplicate messages by logging msgid to a text file using something like this file_put_contents("a.txt", implode(PHP_EOL, $array1), FILE_APPEND);
and then converting it back to an array using $array1 = file("a.txt"); I would also like to delete messages from the array if they are from a set name
I know how to convert json to an array $array1 = json_decode($json, true);
Json Reply from an api that I cannot control
{
"API": "Online",
"MSG": [
{
"info": {
"name": "example"
},
"msg": "example",
"msgid": "example"
},
{
"info": {
"name": "example"
},
"msg": "example",
"msgid": "example"
}
]
}
Hi use the following code, first test it out accordingly
$uniqueMessages = unique_multidim_array($messages,'msg');
Usage : Pass the key as the 2nd parameter for which you need to check the uniqueness of array.
<?php
/* Function to handle unique assocative array */
function unique_multidim_array($array, $key) {
/* temp array to hold unique array */
$temp_array = array();
/* array to hold */
$i = 0;
/* array to hold the key for unique array */
$key_array = array();
foreach($array as $val) {
if (!in_array($val[$key], $key_array)) {
$key_array[$i] = $val[$key];
$temp_array[$i] = $val;
}
$i++;
}
return $temp_array;
}
$messages = array(
0 => array(
'info' => array(
'name' => 'example'
),
'msg' => 'example',
'msgid' => 'example'
),
1 => array(
'info' => array(
'name' => 'example 1'
),
'msg' => 'example 1',
'msgid' => 'example 1'
),
3 => array(
'info' => array(
'name' => 'example'
),
'msg' => 'example',
'msgid' => 'example'
)
);
echo '<pre>';
echo '*****************BEFORE***********************<br/>';
var_dump($messages);
echo '*****************AFTER***********************<br/>';
$uniqueMessages = unique_multidim_array($messages,'msg');
var_dump($uniqueMessages);
This works for me this is an modded function click here for original function
function RemoveElementByArray($array, $key, $seen){
foreach($array as $subKey => $subArray){
if(in_array($subArray[$key], $seen)){
unset($array[$subKey]);
}
}
return $array;
}
Example:
$array = array(
array("id" => "1", "name" => "example1"),
array("id" => "2", "name" => "example2"),
array("id" => "3", "name" => "example3"));
$SeenArray = array("1", "2");
print_r(RemoveElementByArray($array, "id", $SeenArray));
Result:
Array
(
[2] => Array
(
[id] => 3
[name] => example3
)
)
I have tried for several weeks to get this to work, and have given in. I need to display the following array in JSON.
As you can see, [coloroptions] is itself a JSON array, making this a multidimensional array. The trick is (I think) to iterate over the array, first on the child [coloroptions], then on the parent. I am probably way off base, though. Has anyone done anything like this?
Thank you, in advance!
SAMPLE DATA from print_r()
Array
(
[0] => Array
(
[id] => 1
[automobile] => 'Mustang'
[coloroptions] => [{"color":"red"},{"color":"blue"},{"color":"green"}]
)
[1] => Array
(
[id] => 2
[automobile] => 'Camero'
[coloroptions] => [{"color":"red"},{"color":"orange"}]
)
)
JSON output
[
{
"id": 1,
"automobile": "Mustang",
"color": "red"
},
{
"id": 1,
"automobile": "Mustang",
"color": "blue"
},
{
"id": 1,
"automobile": "Mustang",
"color": "green"
},
{
"id": 2,
"automobile": "Camero",
"color": "red"
},
{
"id": 2,
"automobile": "Camero",
"color": "orange"
},
]
I think you're close! My approach would be to use json_decode on the colours, and iterate over them like a normal PHP array.
// First, start by looping through each 'parent':
foreach($array as $key => $value)
{
// Decode the json color array into a normal php array
$colorarray = json_decode($value['coloroptions'], true);
/* Loop through each of the colours.
(Note that they'll be a few layers deep.
Do a print_r($colorarray) to see it's structure) */
foreach($colorarray as $color)
{
// And build your output array:
$output[] = array(
"id" => $value['id'],
"automobile" => $value['automobile'],
"color" => $color['color']
);
}
}
To check the final PHP array you can print_r($output). To convert $output into a json array, use json_encode
json_encode($output);
Well , you need to json_decode the coloroptions and output the assembled array with colors inside it to the result array.
$a = array(
array(
'id' => 1,
'automobile' => 'Mustang',
'coloroptions' => '[{"color":"red"},{"color":"blue"},{"color":"green"}]'
),
array(
'id' => 2,
'automobile' => 'Camero',
'coloroptions' => '[{"color":"red"},{"color":"orange"}]'
),
);
$result = array();
foreach($a as $key => $value) {
$coloroptions = json_decode($value['coloroptions']);
foreach($coloroptions as $color){
$result[] = array(
'id' => $value['id'],
'automobile' => $value['automobile'],
'color' => $color->color,
);
}
}
print_r(json_encode($result));
see the example here