PHP arrays: get value by index where - php

I have this PHP array:
$statuses = array(
'delivery-ongoing' => array("status" => "at-10", "traffic" => "FCL", "type" => "export"),
'delivered' => array("status" => "at-13", "traffic" => "FCL", "type" => "export"),
'delivery-ongoing' => array("status" => "00--00", "traffic" => "FCL", "type" => "import"),
'return-to-ongoing' => array("status" => "to-04", "traffic" => "FCL", "type" => "import"),
'delivered' => array("status" => "at-13", "traffic" => "FCL", "type" => "import")
);
I have to select status by key "delivery-ongoing" where type = "import"
I can play with the array structure since is a constant within my class.
I tried
$statuses['delivery-ongoing']['status']
How do I get the right status for type = "import"
Is there a sort of loop I have to do or there is another way to do this?

You can use array_filter
$filtered = array_filter($statuses, function($value, $key) {
return ($key == 'delivery-ongoing' && $value['type'] == 'import');
}, ARRAY_FILTER_USE_BOTH);
print_r($filtered);
Also, as it has been suggested in the comments, you can re-name your keys, maybe by appending an ID after the status.
Eq:
'delivery-ongoing-101' => array("status" => "at-10", "traffic" => "FCL", "type" => "export"),

There are several problems with this array:
1- There's an error in a parenthesis that is closed too early at this line:
'return-to-ongoing' => array("status" => "to-04", "traffic" => "FCL"), "type" => "import",
2- If you define the same key two times on the same array, you won't be able to access the first element that was defined with this key. If you use a debugger, you will see that only 3 elements are available in your array, cause there are more than one that share the same key and only the last one is saved.
But to get the value that you are looking for, you can use this loop:
foreach ($statuses as $key => $value) {
if($key == 'delivery-ongoing' && $value['type'] == 'import'){
$result = $value['status'];
break;
}
}
The status for the type import is available at $result after the loop ends.

Your $statuses must have the following structure:
$statuses = array(
'delivery-ongoing' => array(
array("status" => "at-10", "traffic" => "FCL", "type" => "export"),
array("status" => "00--00", "traffic" => "FCL", "type" => "import")
),
'delivered' => array(
array("status" => "at-13", "traffic" => "FCL", "type" => "export"),
array("status" => "at-13", "traffic" => "FCL", "type" => "import")
),
'return-to-ongoing' => array(array("status" => "to-04", "traffic" => "FCL", "type" => "import")),
);
Now, you can do what you want to do by doing:
function filter_by_value ($array, $index, $value){
if(is_array($array) && count($array)>0)
{
foreach(array_keys($array) as $key){
$temp[$key] = $array[$key][$index];
if ($temp[$key] == $value){
$newarray[$key] = $array[$key];
}
}
}
return $newarray;
}
$imported = filter_by_value($statuses['delivery-ongoing'], 'type', 'import');
print_r($imported);

Related

Intersection of one multidimensional arrays in PHP

I have the following array :
$output = array(
1507073550 => array(
0 => array(
"userid" => "1507073550"
"username" => "ma_alikhani"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/75538099_557824008392923_8054831368279949312_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
1 => array(
"userid" => "11863258101"
"username" => "rasouli680"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/70326284_949495768737898_5241573836020776960_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
2 => array(
"userid" => "16528062"
"username" => "alireza"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/70597112_740563976416368_5253996423334068224_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
)
16528062 => array(
0 => array(
"userid" => "16528062"
"username" => "alireza"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/70597112_740563976416368_5253996423334068224_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
1 => array(
"userid" => "1507073550"
"username" => "ma_alikhani"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/75538099_557824008392923_8054831368279949312_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
)
)
and I want to intersection of keys of this array. get first key "1507073550" and second key "16528062" and intersect all of their data.
it's not always have 2 keys, it might have +2 keys, i wrote this code but I'm getting array to string conversion error.
$keys = array_keys($output);
foreach ($keys as $index => $values)
{
$current_value = $output[$values]; // or $current_value = $a[$keys[$index]];
$next_key = next($keys);
$next_value = $output[$next_key] ?? null; // for php version >= 7.0
$a[] = array_intersect_assoc($current_value,$next_value);
}
and I'm expecting this result :
array(
0 => array(
"userid" => "1507073550"
"username" => "ma_alikhani"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/75538099_557824008392923_8054831368279949312_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
1 => array(
"userid" => "16528062"
"username" => "alireza"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/70597112_740563976416368_5253996423334068224_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
)
I really don't know how to do it !
I'd be appreciated for your helps.
function intersect(array $src, array $keys)
{
// Require that both $src and $keys have data
if (!$src || !$keys) {
return [];
}
// Hold the users for each key in $keys
$sets = [];
// Store the users from $src to $sets as dictated by $keys
foreach ($keys as $key) {
if (isset($src[$key])) {
// Re-key the list of users with their user id
$userIds = array_column($src[$key], 'userid');
$sets[$key] = array_combine($userIds, $src[$key]);
}
}
if (count($sets) !== count($keys)) {
// Up to you if you want to require that all keys must be valid/present in the $src
}
// Get the users present in all of the set dictated by $keys
$users = call_user_func_array('array_intersect_key', $sets);
return $users;
};
To use:
$output = [ ... ]; // $ouput in the question
$keys = [1507073550, 16528062]; // see question
$users = intersect($output, $keys);

Remove duplicates from a multidimensional array based on multiple keys

Sorry if this was asked before, but I searched a lot and couldn't find a solution.
I've been trying to solve this problem for a while now, and couldn't write the function for it.
I have an array like that:
$numbers = array(
array("tag" => "developer", "group" => "grp_1", "num" => "123123"),
array("tag" => "developer", "group" => "grp_2", "num" => "111111"),
array("tag" => "student", "group" => "grp_1", "num" => "123123"),
array("tag" => "student", "group" => "grp_2", "num" => "123123"),
array("tag" => "developer", "group" => "grp_3", "num" => "111111"),
);
I need to write a function, that removes the duplicates off this array, based on multiple keys, so my function call should look something like that:
unique_by_keys($numbers, array("num","group"));
In other terms, one number can't be in the same group more than once.
After calling unique_by_keys() by array should be like that:
$numbers = array(
array("tag" => "developer", "group" => "grp_1", "num" => "123123"),
array("tag" => "developer", "group" => "grp_2", "num" => "111111"),
array("tag" => "student", "group" => "grp_2", "num" => "123123"),
array("tag" => "developer", "group" => "grp_3", "num" => "111111"),
);
I'd appreciate if you could help me find a solution, or lead me to the correct way of thinking.
Thanks!
SOLUTION:
I was able to find a solution, by writing the following function:
( I wrote it in a way that accepts many forms of $haystack arrays )
function unique_by_keys($haystack = array(), $needles = array()) {
if (!empty($haystack) && !empty($needles)) {
$_result = array();
$result = array();
$i = 0;
foreach ($haystack as $arrayObj) {
if (is_array($arrayObj)) {
$searchArray = array();
foreach ($needles as $needle) {
if (isset($arrayObj[$needle])) {
$searchArray[$needle] = $arrayObj[$needle];
}
}
if (!in_array($searchArray, $_result)) {
foreach ($arrayObj as $key => $value) {
if (in_array($key, $needles)) {
$_result[$i][$key] = $value;
}
}
$result[] = array_merge($_result[$i], $arrayObj);
}
} else {
$result[] = $arrayObj;
}
$i++;
}
return $result;
}
}
Thanks for everyone that replied!
Bhaskar's approach which assigns unique keys in the loop to remove duplicates affords a very small function for this case.
Here is a previous and unnecessarily complicated version:
function unique_by_keys($haystack=array(),$needles=array()){
// reverse order of sub-arrays to preserve lower-indexed values
foreach(array_reverse($haystack) as $row){
$result[implode('',array_intersect_key($row,array_flip($needles)))]=$row; // assign unique keys
}
ksort($result); // sort the sub-arrays by their assoc. keys
return array_values($result); // replace assoc keys with indexed keys
}
This is the best/leanest solution I can come up with:
$numbers = array(
array("tag" => "developer", "group" => "grp_1", "num" => "123123"),
array("tag" => "developer", "group" => "grp_2", "num" => "111111"),
array("tag" => "student", "group" => "grp_1", "num" => "123123"),
array("tag" => "student", "group" => "grp_2", "num" => "123123"),
array("tag" => "developer", "group" => "grp_3", "num" => "111111")
);
function unique_by_keys($haystack=array(),$needles=array()){
foreach($haystack as $row){
$key=implode('',array_intersect_key($row,array_flip($needles))); // declare unique key
if(!isset($result[$key])){$result[$key]=$row;} // save row if non-duplicate
}
return array_values($result);
}
echo "<pre>";
var_export(unique_by_keys($numbers,array("group","num")));
echo "</pre>";
Output:
array (
0 =>
array (
'tag' => 'developer',
'group' => 'grp_1',
'num' => '123123',
),
1 =>
array (
'tag' => 'developer',
'group' => 'grp_2',
'num' => '111111',
),
2 =>
array (
'tag' => 'student',
'group' => 'grp_2',
'num' => '123123',
),
3 =>
array (
'tag' => 'developer',
'group' => 'grp_3',
'num' => '111111',
),
)
$newNumbers = array();
foreach($numbers as $key=>$values){
$newkey = $values['group'].'__'.$values['num'];
$newNumbers[$newkey] = $values;
}
var_dump($newNumbers)
Code might not be efficient, but i will work for you :)
$result = unique_by_keys($numbers, array("num","group"));
echo "<pre>";
print_R($result);
function unique_by_keys($numbers, $arr){
$new_array = array();
$output = array();
foreach ($numbers as $n){
if(isset($new_array[$n[$arr[1]]]) && $new_array[$n[$arr[1]]] == $n[$arr[0]]){
continue;
}else{
$new_array[$n[$arr[1]]] = $n[$arr[0]];
$output[] = $n;
}
}
return $output;
}

Sorting array by value

I have this array:
array(
"tour_0" => 1446,
"tour_1" => 1471,
"date-from-1471" => "2014-08-07",
"date-to-1471" => "2014-08-15",
"tour_2" => 30,
"date-from-30" => 2014-08-01,
"date-to-30" => 2014-08-05,
"tour_3" => 10
)
Now, i need it to be sorted to this:
array(
"0" => array("ID" => 1446),
"1" => array("ID" => 1471, "from" => "2014-08-07", "to" => "2014-08-15"),
"2" => array("ID" => 30, "from" => "2014-08-07", "to" => "2014-08-15"),
"3" => array("ID" => 10),
)
How can i accomplish this thing?
I've tried all sorts of things but i can't seem to figure this one out...
Thank's and sorry about the title but i just don't know how to describe it.
How about this?
$ret = [];
foreach($inputArray as $key => $value) {
if (preg_match('/^tour_([0-9]+)/', $key)) {
$ret[$value] = ["ID" => $value];
}
if (preg_match('/date-from-([0-9]+)/', $key, $matches)) {
$ret[$matches[1]]["from"] = $value;
}
if (preg_match('/date-to-([0-9]+)/', $key, $matches)) {
$ret[$matches[1]]["to"] = $value;
}
}
print_r($ret);
/*
Array
(
"1446" => Array ("ID" => 1446),
"1471" => Array ("ID" => 1471, "from" => "2014-08-07", "to" => "2014-08-15"),
"30" => Array ("ID" => 30, "from" => "2014-08-01", "to" => "2014-08-05"),
"10" => Array ("ID" => 10)
)*/
Close enough? (it is quite trival change the keys of the array, considering they are in order (0, 1, 2, 3, ...), if they are not, maybe you can save the order also (in another item of the subarray) and recompose again once this array is formed)

Using foreach and nested array to insert rows in MySql with PHP

I've written the follow code to try and insert data into a table on the database. However it's just inserting letters. I'm not sure what I'm doing wrong.
$media_items = array(
array (
"media_name" => "Facebook",
"link_url" => "http://www.facebook.com/insightdezign",
"icon" => "facebook.png",
"size" => "48",
"order" => "0"
),
array (
"media_name" => "Twitter",
"link_url" => "http://www.twitter.com/insightdezign",
"icon" => "twitter.png",
"size" => "48",
"order" => "1"
)
);
foreach ($media_items as $media_item) {
if (is_array($media_item)){
foreach ($media_item as $item) {
$rows_affected = $wpdb->insert( $ffui_items, array( 'media_name' => $item['media_name'], 'link_url' => $item['link_url'], 'icon' => $item['icon'], 'size' => $item['size'], 'order' => $item['order'] ) );
}
}
}
Inside your nested foreach loop, you will be looping over strings, not arrays. As a result of type juggling, the indexes will be evaluated to 0. Since PHP also accepts $foo['bar'] syntax on strings, it will just return the first letter.
You can simply remove the nested foreach loop and do it as follows:
foreach ($media_items as $media_item)
{
if (is_array($media_item))
{
$rows_affected = $wpdb->insert( $ffui_items,
array(
'media_name' => $media_item['media_name'],
'link_url' => $media_item['link_url'],
'icon' => $media_item['icon'],
'size' => $media_item['size'],
'order' => $media_item['order']
) ;
}
}

Convert multidimensional array into XML

Please read the bolded line below before you comment that this may be a duplicate. This has nothing to do with SimpleXML.
Let me start off by showing how the XML should be laid out. Please ignore the namespaces:
<hot:SearchHotels>
<hot:request>
<hot1:Destination>?</hot1:Destination>
<hot1:HotelCityName>?</hot1:HotelCityName>
<hot1:HotelLocationName>?</hot1:HotelLocationName>
<hot1:HotelName>?</hot1:HotelName>
<hot1:CheckIn>?</hot1:CheckIn>
<hot1:CheckOut>?</hot1:CheckOut>
<hot1:RoomsInformation>
<!--Zero or more repetitions:-->
<hot1:RoomInfo>
<hot1:AdultNum>?</hot1:AdultNum>
<hot1:ChildNum>?</hot1:ChildNum>
<!--Optional:-->
<hot1:ChildAges>
<!--Zero or more repetitions:-->
<hot1:ChildAge age="?"/>
</hot1:ChildAges>
</hot1:RoomInfo>
</hot1:RoomsInformation>
<hot1:MaxPrice>?</hot1:MaxPrice>
<hot1:StarLevel>?</hot1:StarLevel>
<hot1:AvailableOnly>?</hot1:AvailableOnly>
<hot1:PropertyType>?</hot1:PropertyType>
<hot1:ExactDestination>?</hot1:ExactDestination>
</hot:request>
</hot:SearchHotels>
Notice under hot1:RoomsInformation there is RoomInfo. I'm supposed to be able to send multiple RoomInfo nodes. But I'm using a PHP class to convert an array to this object to be submitted via SOAP.
Here's my array before it gets converted to an object:
$param = array(
"Destination" => $destcode,
"HotelCityName" => $city,
"HotelLocationName" => "",
"HotelName" => "",
"CheckIn" => date("Y-m-d", strtotime($checkin)),
"CheckOut" => date("Y-m-d", strtotime($checkout)),
"RoomsInformation" => array (
"RoomInfo" => array(
"AdultNum" => 2,
"ChildNum" => 1,
"ChildAges" => array(
"ChildAge" => array(
"age"=>11
)
)
),
"RoomInfo" => array(
"AdultNum" => 1,
"ChildNum" => 0,
"ChildAges" => array(
"ChildAge" => array(
"age"=>0
)
)
)
),
"MaxPrice" => 0,
"StarLevel" => 0,
"AvailableOnly" => "false",
"PropertyType" => "NotSet",
"ExactDestination" => "false"
);
$param = arrayToObject($param) ;
$obj = new stdClass();
$obj->request=$param;
$result = $test->SearchHotels($obj) ;
The problem is that after converting to an Object, there is only 1 RoomInfo and its the last one. My thought is because the RoomsInformation array has 2 identical KEY names. So how can I make this work?
For your information, here is the SOAP class I use and the arrayToObject function:
http://pastebin.com/SBUN0FAF
The problem is, your array is invalid as you suspected because of the duplicate keys. One way to solve the issue is to wrap each "RoomInfo" in its own array like so:
$param = array(
"Destination" => $destcode,
"HotelCityName" => $city,
"HotelLocationName" => "",
"HotelName" => "",
"CheckIn" => date("Y-m-d", strtotime($checkin)),
"CheckOut" => date("Y-m-d", strtotime($checkout)),
"RoomsInformation" => array (
array(
"RoomInfo" => array(
"AdultNum" => 2,
"ChildNum" => 1,
"ChildAges" => array(
"ChildAge" => array(
"age"=>11
)
)
),
),
array(
"RoomInfo" => array(
"AdultNum" => 1,
"ChildNum" => 0,
"ChildAges" => array(
"ChildAge" => array(
"age"=>0
)
)
)
)
),
"MaxPrice" => 0,
"StarLevel" => 0,
"AvailableOnly" => "false",
"PropertyType" => "NotSet",
"ExactDestination" => "false"
);
And you can generate the XML like this:
// create simpleXML object
$xml = new SimpleXMLElement("<?xml version=\"1.0\"?><SearchHotels></SearchHotels>");
$node = $xml->addChild('request');
// function call to convert array to xml
array_to_xml($param, $node);
// display XML to screen
echo $xml->asXML();
die();
// function to convert an array to XML using SimpleXML
function array_to_xml($array, &$xml) {
foreach($array as $key => $value) {
if(is_array($value)) {
if(!is_numeric($key)){
$subnode = $xml->addChild("$key");
array_to_xml($value, $subnode);
} else {
array_to_xml($value, $xml);
}
} else {
$xml->addChild("$key","$value");
}
}
}
I attribute the array_to_xml function to the wonderful author here: https://stackoverflow.com/a/5965940/2200766
It looks as though you should have your array like this, instead;
$param = array(
"Destination" => $destcode,
"HotelCityName" => $city,
"HotelLocationName" => "",
"HotelName" => "",
"CheckIn" => date("Y-m-d", strtotime($checkin)),
"CheckOut" => date("Y-m-d", strtotime($checkout)),
"RoomsInformation" => array (
"RoomInfo" => array(
array(
"AdultNum" => 2,
"ChildNum" => 1,
"ChildAges" => array(
"ChildAge" => array(
"age"=>11
)
)
),
array(
"AdultNum" => 1,
"ChildNum" => 0,
"ChildAges" => array(
"ChildAge" => array(
"age"=>0
)
)
)
)
),
"MaxPrice" => 0,
"StarLevel" => 0,
"AvailableOnly" => "false",
"PropertyType" => "NotSet",
"ExactDestination" => "false"
);
This will preserve the two RoomInfo array elements.
simply use this function, where $data is multideminsional array
function array_to_xml( $data ) {
$xml_data = new SimpleXMLElement('<?xml version="1.0"?><data></data>');
foreach( $data as $key => $value ) {
$node = $xml_data->addChild('row_' . $key);
foreach( $value as $keyx => $valuex ) {
$node->addChild($keyx,$valuex);
}
}
return $xml_data->asXML();
}

Categories