how to Display values from nested array - php

Please help me to extract and display the values from this array..
This is the output when I do a print_r($array); :
Array
(
[0] => SPD Object
(
[DRIVERNAME] => SPD Barry
[STARTTIME] => 07:44
[FINISHTIME] => 18:12
[STOP] =>
[SEQUENCENO] => 37
[PLACENAME] => AMSTERDAM ZUIDOOST
[ARRIVALTIME] => 17:32
)
[1] => SPD Object
(
[DRIVERNAME] => SPD Brady
[STARTTIME] => 07:36
[FINISHTIME] => 15:53
[STOP] =>
[SEQUENCENO] => 32
[PLACENAME] => NIEUWEGEIN
[ARRIVALTIME] => 15:30
)
[2] => SPD Object
(
[DRIVERNAME] => SPD Bram
[STARTTIME] => 08:11
[FINISHTIME] => 18:32
[STOP] =>
[SEQUENCENO] => 32
[PLACENAME] => LAGE ZWALUWE
[ARRIVALTIME] => 17:28
)
)
What I want to do is, get this Driver Name and Sequence Number and echo them.
UPDATE :
My full code can be found below.
I get a xml file which contain this kind of stuff :
<TRIP>
<DRIVERNAME>SPD Barry</DRIVERNAME>
<STARTTIME>07:44</STARTTIME>
<FINISHTIME>18:12</FINISHTIME>
<STOP>
<SEQUENCENO>1</SEQUENCENO>
<PLACENAME>ROTTERDAM</PLACENAME>
<ARRIVALTIME>08:30</ARRIVALTIME>
</STOP>
</TRIP>
Here is my PHP file to collect data into an array.
<?php
class SPD {
function SPD ($aa) {
foreach ($aa as $k=>$v)
$this->$k = $aa[$k];
}
}
function readDatabase($filename) {
// read the XML database of aminoacids
$data = implode("", file($filename));
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($parser, $data, $values, $tags);
xml_parser_free($parser);
// loop through the structures
foreach ($tags as $key=>$val) {
if ($key == "TRIP") {
$molranges = $val;
// each contiguous pair of array entries are the
// lower and upper range for each molecule definition
for ($i=0; $i < count($molranges); $i+=2) {
$offset = $molranges[$i] + 1;
$len = $molranges[$i + 1] - $offset;
$tdb[] = parseMol(array_slice($values, $offset, $len));
}
} else {
continue;
}
}
return $tdb;
}
function parseMol($mvalues) {
for ($i=0; $i < count($mvalues); $i++) {
$mol[$mvalues[$i]["tag"]] = $mvalues[$i]["value"];
}
return new SPD($mol);
}
$db = readDatabase("test.xml");
if(is_array($db)){
foreach($db as $item) {
echo $item->DRIVERNAME;
echo $item->SEQUENCENO;
}
}
?>
What I want to do is, echo Driver name and Sequence Number :)

This should do it :
<?php
class SPD {
function SPD($aa) {
foreach ($aa as $k => $v)
$this->$k = $aa[$k];
}
}
function readDatabase($filename) {
// read the XML database of aminoacids
$data = implode("", file($filename));
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($parser, $data, $values, $tags);
xml_parser_free($parser);
// loop through the structures
foreach ($tags as $key => $val) {
if ($key == "TRIP") {
$molranges = $val;
// each contiguous pair of array entries are the
// lower and upper range for each molecule definition
for ($i = 0; $i < count($molranges); $i+=2) {
$offset = $molranges[$i] + 1;
$len = $molranges[$i + 1] - $offset;
$tdb[] = parseMol(array_slice($values, $offset, $len));
}
} else {
continue;
}
}
return $tdb;
}
function parseMol($mvalues) {
for ($i = 0; $i < count($mvalues); $i++) {
if(isset($mvalues[$i]["value"])) {
$mol[$mvalues[$i]["tag"]] = $mvalues[$i]["value"];
}
}
return new SPD($mol);
}
$db = readDatabase("test.xml");
if (is_array($db)) {
foreach ($db as $item) {
echo 'ITEM 1 : ' . "\n<br/>";
echo '---------------' . "\n<br/>";
echo 'DRIVERNAME : ' . $item->DRIVERNAME . "\n<br/>";
echo 'SEQUENCENO : ' . $item->SEQUENCENO . "\n\n<br/><br/>";
}
}
?>

Related

get sum of php multidiamentional array

I am looking to store sum of all keys inside an array here is my example code
<?php
// Sample data
$category = (object) ['category_name' => '32459*1500*lab*1,32460*400*lab*1,32461*600*lab*1'];
// process
$category_sale_data = explode(',', $category->category_name);
foreach ($category_sale_data as $key => $value) {
list($sale_key, $sale_value) = explode('*', $value);
$category->sale_data[$sale_key][] = $sale_value;
//$category->sale_data_sum[$sale_key][] += $sale_value;
}
// display
print_r($category);
getting this output working example -> https://3v4l.org/NAKfb#v7.0.0
Here is expected to get //$category->sale_data_sum[$sale_key][] +=
$sale_value;
I am expected output like this
stdClass Object
(
[category_name] => 32459*1500*lab*1,32460*400*lab*1,32461*600*lab*1
[sale_data] => Array
(
[32459] => Array
(
[0] => 1500
)
[32460] => Array
(
[0] => 400
)
[32461] => Array
(
[0] => 600
)
)
[sale_data_sum] => 2500
)
Simply do this:
$category->sale_data_sum = 0; // initiate key
foreach ($category_sale_data as $key => $value) {
list($sale_key, $sale_value) = explode('*', $value);
$category->sale_data[$sale_key][] = $sale_value;
$category->sale_data_sum += $sale_value; // add each sale value
}
$category = [ 'category_name' => '32459*1500*lab*1,32460*400*lab*1,32461*600*lab*1' ];
// category_name
$result['category_name'] = $category['category_name'];
// sale_data
$splitted = preg_split('/[*,]/', $category['category_name']);
for($i = 0; $i < count($splitted); $i += 4) {
$result['sale_data'][$splitted[$i]] = $splitted[$i + 1];
}
// sale_data_sum
$result['sale_data_sum'] = array_sum($result['sale_data']);
print_r($result);
Try this
<?php
// Sample data
$category = (object) ['category_name' => '32459*1500*lab*1,32460*400*lab*1,32461*600*lab*1'];
// process
$category_sale_data = explode(',', $category->category_name);
foreach ($category_sale_data as $key => $value) {
list($sale_key, $sale_value) = explode('*', $value);
$category->sale_data[$sale_key][] = $sale_value;
//$category->sale_data_sum[$sale_key][] += $sale_value;
}
function sum($carry, $item)
{
$carry += array_values($item)[0];
return $carry;
}
$a = array_reduce(array_values($category->sale_data), "sum");
var_dump($a);
Or
<?php
// Sample data
$category = (object) ['category_name' => '32459*1500*lab*1,32460*400*lab*1,32461*600*lab*1'];
// process
$category_sale_data = explode(',', $category->category_name);
$category->sale_data_sum = null;
foreach ($category_sale_data as $key => $value) {
list($sale_key, $sale_value) = explode('*', $value);
$category->sale_data[$sale_key][] = $sale_value;
$category->sale_data_sum += $sale_value;
}
// display
print_r($category);

how to check if SplFixedArray contains value?

with a normal array one would use in_array() , but in_array doesn't support SplFixedArray, and i couldn't really find any splFixedArray in_array() equivalent, i could just foreach-loop it myself like
function spl_in_array(\SplFixedArray &$arr, $value): bool
{
foreach ($arr as $val) {
if ($val === $value) {
return true;
}
}
return false;
}
but that appears to be ~14-17 times slower than in_array(), and since the whole point of SplFixedArray is performance and memory usage (i think?)... with this benchmark code
<?php
declare(strict_types = 1);
$check_iterations = 100;
$nbr_array_values = 100000;
$lookup_value = round($nbr_array_values / 2);
function format(float $f): string
{
return number_format($f, 6);
}
function spl_in_array(\SplFixedArray &$arr, $value): bool
{
foreach ($arr as $val) {
if ($val === $value) {
return true;
}
}
return false;
}
$arr = [];
for ($i = 0; $i < $nbr_array_values; ++ $i) {
$arr[] = $i;
}
$splArr = SplFixedArray::fromArray($arr);
$results = [];
$start = microtime(true);
for ($i = 0; $i < $check_iterations; ++ $i) {
in_array($lookup_value, $arr, true);
}
$end = microtime(true);
$results["in_array"] = $end - $start;
$start = microtime(true);
for ($i = 0; $i < $check_iterations; ++ $i) {
spl_in_array($splArr, $lookup_value);
}
$end = microtime(true);
$results["spl_in_array"] = ($end - $start);
$results["in_array/spl_in_array"] = $results["in_array"] / $results["spl_in_array"];
$results["spl_in_array/in_array"] = $results["spl_in_array"] / $results["in_array"];
$fastest = ($results["in_array"] > $results["spl_in_array"]) ? "spl_in_array" : "in_array";
foreach ($results as &$result) {
$result = format($result);
}
$results["fastest"] = $fastest;
print_r($results);
i get
Array
(
[in_array] => 0.001330
[spl_in_array] => 0.019912
[in_array/spl_in_array] => 0.066801
[spl_in_array/in_array] => 14.969887
[fastest] => in_array
)
Array
(
[in_array] => 0.001024
[spl_in_array] => 0.015516
[in_array/spl_in_array] => 0.065997
[spl_in_array/in_array] => 15.152270
[fastest] => in_array
)
Array
(
[in_array] => 0.001124
[spl_in_array] => 0.015159
[in_array/spl_in_array] => 0.074140
[spl_in_array/in_array] => 13.487908
[fastest] => in_array
)
Array
(
[in_array] => 0.000838
[spl_in_array] => 0.013853
[in_array/spl_in_array] => 0.060495
[spl_in_array/in_array] => 16.530299
[fastest] => in_array
)
Array
(
[in_array] => 0.000960
[spl_in_array] => 0.014201
[in_array/spl_in_array] => 0.067609
[spl_in_array/in_array] => 14.790911
[fastest] => in_array
)
Array
(
[in_array] => 0.000865
[spl_in_array] => 0.015183
[in_array/spl_in_array] => 0.056970
[spl_in_array/in_array] => 17.553197
[fastest] => in_array
)
so doing it manually with a foreach() is evidently not a particularly efficient way of doing it..
hence the question, how should i check if a SplFixedArray contains something? what is the SplFixedArray-equivalent of in_array() ?
If you make use of the ->toArray() method to convert the spl array to a standard PHP Array and then use in_array() you can reduce the time enormously
$check_iterations = 100;
$nbr_array_values = 100000;
$lookup_value = round($nbr_array_values / 2);
function format(float $f): string
{
return number_format($f, 6);
}
function spl_in_array(\SplFixedArray &$arr, $value): bool
{
foreach ($arr as $val) {
if ($val === $value) {
return true;
}
}
return false;
}
function new_spl_in_array(\SplFixedArray &$arr, $value): bool
{
$a = $arr->toArray();
return in_array($value, $a);
}
$arr = [];
for ($i = 0; $i < $nbr_array_values; ++ $i) {
$arr[] = $i;
}
$splArr = SplFixedArray::fromArray($arr);
$results = [];
$start = microtime(true);
for ($i = 0; $i < $check_iterations; ++ $i) {
in_array($lookup_value, $arr, true);
}
$end = microtime(true);
$results["in_array"] = $end - $start;
$start = microtime(true);
for ($i = 0; $i < $check_iterations; ++ $i) {
spl_in_array($splArr, $lookup_value);
}
$end = microtime(true);
$results["spl_in_array"] = ($end - $start);
$start = microtime(true);
for ($i = 0; $i < $check_iterations; ++ $i) {
new_spl_in_array($splArr, $lookup_value);
}
$end = microtime(true);
$results["spl_in_array_new"] = ($end - $start);
$results["in_array/spl_in_array"] = $results["in_array"] / $results["spl_in_array"];
$results["spl_in_array/in_array"] = $results["spl_in_array"] / $results["in_array"];
$fastest = ($results["in_array"] > $results["spl_in_array"]) ? "spl_in_array" : "in_array";
foreach ($results as &$result) {
$result = format($result);
}
$results["fastest"] = $fastest;
print_r($results);
RESULTS
Array
(
[in_array] => 0.011569
[spl_in_array] => 1.094222
[spl_in_array_new] => 0.157041 // < Using ->toArray()
[in_array/spl_in_array] => 0.010573
[spl_in_array/in_array] => 94.583991
[fastest] => in_array
)

loop through multidimensional array php - get all index and implode to string

I am stuck with a part of my code and i can't see to figure out why i get a certain result. What my goal is to loop through the array and echo this result as a string:
First Array
validate.required
validate.remote
Second array
shop.cart.string
Current result is:
validate.0.required
validate.1.remote
It returns the index from the array, how can solve this/remove this from my string?
private $translationKeys = [
'validate' => [
'required',
'remote',
'email',
'url',
'date',
'dateISO',
'number',
'digits',
'creditcard',
'equalTo',
'extension',
'maxlength',
'minlength',
'rangelength',
'range',
'max',
'min',
'step'
],
'shop' => [
'cart' => [
'string'
],
],
];
​
This is my function:
function listArrayRecursive($translationKeys) {
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($translationKeys), RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $k => $v) {
if ($iterator->hasChildren()) {
} else {
for ($p = array(), $i = 0, $z = $iterator->getDepth(); $i <= $z; $i++) {
$p[] = $iterator->getSubIterator($i)->key();
$y = array();
foreach ($p as $value) {
array_push($y, $value);
}
}
$path = implode('.', $y);
$a[] = "$path.$v<br>";
// Here i want to echo the string
}
}
}
Second version of the function
function listArrayRecursive($translationKeys) {
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($translationKeys), RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $k => $v) {
if ($iterator->hasChildren()) {
} else {
for ($p = array(), $i = 0, $z = $iterator->getDepth(); $i <= $z; $i++) {
$p[] = $iterator->getSubIterator($i)->key();
}
$path = implode('.', $p);
$a[] = "$path.$v<br>";
}
}
}
Here's a function that will give you the result you desire. It recurses through each element of the array that is an array, concatenating the key with the values, or just returns the value if it is not an array:
function listArrayRecursive($array) {
$list = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
foreach (listArrayRecursive($value) as $v) {
$list[] = "$key.$v";
}
}
else {
$list[] = $value;
}
}
return $list;
}
print_r(listArrayRecursive($translationKeys));
Output:
Array (
[0] => validate.required
[1] => validate.remote
[2] => validate.email
[3] => validate.url
[4] => validate.date
[5] => validate.dateISO
[6] => validate.number
[7] => validate.digits
[8] => validate.creditcard
[9] => validate.equalTo
[10] => validate.extension
[11] => validate.maxlength
[12] => validate.minlength
[13] => validate.rangelength
[14] => validate.range
[15] => validate.max
[16] => validate.min
[17] => validate.step
[18] => shop.cart.string
)
Demo on 3v4l.org
try something like this
function disp_array_rec($arr, $upper = null) {
foreach ($arr as $k => $v) {
echo ($upper != null ? $upper : "");
if (is_array($v)) {
disp_array_rec($v, $k . ".");
} else {
echo "$v\n";
}
}
}
disp_array_rec($translationKeys);
result:
validate.required
validate.remote
validate.email
validate.url
validate.date
validate.dateISO
validate.number
validate.digits
validate.creditcard
validate.equalTo
validate.extension
validate.maxlength
validate.minlength
validate.rangelength
validate.range
validate.max
validate.min
validate.step
shop.cart.string

Is there something like keypath in an associative array in PHP?

I want to dissect an array like this:
[
"ID",
"UUID",
"pushNotifications.sent",
"campaigns.boundDate",
"campaigns.endDate",
"campaigns.pushMessages.sentDate",
"pushNotifications.tapped"
]
To a format like this:
{
"ID" : 1,
"UUID" : 1,
"pushNotifications" :
{
"sent" : 1,
"tapped" : 1
},
"campaigns" :
{
"boundDate" : 1,
"endDate" : 1,
"pushMessages" :
{
"endDate" : 1
}
}
}
It would be great if I could just set a value on an associative array in a keypath-like manner:
//To achieve this:
$dissected['campaigns']['pushMessages']['sentDate'] = 1;
//By something like this:
$keypath = 'campaigns.pushMessages.sentDate';
$dissected{$keypath} = 1;
How to do this in PHP?
You can use :
$array = [
"ID",
"UUID",
"pushNotifications.sent",
"campaigns.boundDate",
"campaigns.endDate",
"campaigns.pushMessages.sentDate",
"pushNotifications.tapped"
];
// Build Data
$data = array();
foreach($array as $v) {
setValue($data, $v, 1);
}
// Get Value
echo getValue($data, "campaigns.pushMessages.sentDate"); // output 1
Function Used
function setValue(array &$data, $path, $value) {
$temp = &$data;
foreach(explode(".", $path) as $key) {
$temp = &$temp[$key];
}
$temp = $value;
}
function getValue($data, $path) {
$temp = $data;
foreach(explode(".", $path) as $ndx) {
$temp = isset($temp[$ndx]) ? $temp[$ndx] : null;
}
return $temp;
}
function keyset(&$arr, $keypath, $value = NULL)
{
$keys = explode('.', $keypath);
$current = &$arr;
while(count($keys))
{
$key = array_shift($keys);
if(!isset($current[$key]) && count($keys))
{
$current[$key] = array();
}
if(count($keys))
{
$current = &$current[$key];
}
}
$current[$key] = $value;
}
function keyget($arr, $keypath)
{
$keys = explode('.', $keypath);
$current = $arr;
foreach($keys as $key)
{
if(!isset($current[$key]))
{
return NULL;
}
$current = $current[$key];
}
return $current;
}
//Testing code:
$r = array();
header('content-type: text/plain; charset-utf8');
keyset($r, 'this.is.path', 39);
echo keyget($r, 'this.is.path');
var_dump($r);
It's a little rough, I can't guarantee it functions 100%.
Edit: At first you'd be tempted to try to use variable variables, but I've tried that in the past and it doesn't work, so you have to use functions to do it. This works with some limited tests. (And I just added a minor edit to remove an unnecessary array assignment.)
In the meanwhile, I came up with (another) solution:
private function setValueForKeyPath(&$array, $value, $keyPath)
{
$keys = explode(".", $keyPath, 2);
$firstKey = $keys[0];
$remainingKeys = (count($keys) == 2) ? $keys[1] : null;
$isLeaf = ($remainingKeys == null);
if ($isLeaf)
$array[$firstKey] = $value;
else
$this->setValueForKeyPath($array[$firstKey], $value, $remainingKeys);
}
Sorry for the "long" namings, I came from the Objective-C world. :)
So calling this on each keyPath, it actually gives me the output:
fields
Array
(
[0] => ID
[1] => UUID
[2] => pushNotifications.sent
[3] => campaigns.boundDate
[4] => campaigns.endDate
[5] => campaigns.pushMessages.endDate
[6] => pushNotifications.tapped
)
dissectedFields
Array
(
[ID] => 1
[UUID] => 1
[pushNotifications] => Array
(
[sent] => 1
[tapped] => 1
)
[campaigns] => Array
(
[boundDate] => 1
[endDate] => 1
[pushMessages] => Array
(
[endDate] => 1
)
)
)

Parse Unserialized array

i have a unserialized array
like this
Array (
[status] => 1
[msg] => Transaction Fetched Successfully
[transaction_details] => Array (
[100002982] => Array (
[mihpayid] => 4149968
[request_id] => 635788
[bank_ref_num] => NINETE.31845.28052012
[amt] => 3295.00
[disc] => 0.00
[mode] => CC
[retries] => 0
[status] => success
[unmappedstatus] => captured
)
)
)
i want to parse this array
so that i can get the value to status ie Success
how i can do that
$success = $array['transaction_details']['100002982']['status'];
$arr['transaction_details']['100002982']['status']
The PHP documentation has a user comment which suggests a method to parse the output of print_r (similar to the above). It can be found here: http://www.php.net/manual/en/function.print-r.php#93529
Here is a copy of the source code found at the above link:
<?php
function print_r_reverse($in) {
$lines = explode("\n", trim($in));
if (trim($lines[0]) != 'Array') {
// bottomed out to something that isn't an array
return $in;
} else {
// this is an array, lets parse it
if (preg_match("/(\s{5,})\(/", $lines[1], $match)) {
// this is a tested array/recursive call to this function
// take a set of spaces off the beginning
$spaces = $match[1];
$spaces_length = strlen($spaces);
$lines_total = count($lines);
for ($i = 0; $i < $lines_total; $i++) {
if (substr($lines[$i], 0, $spaces_length) == $spaces) {
$lines[$i] = substr($lines[$i], $spaces_length);
}
}
}
array_shift($lines); // Array
array_shift($lines); // (
array_pop($lines); // )
$in = implode("\n", $lines);
// make sure we only match stuff with 4 preceding spaces (stuff for this array and not a nested one)
preg_match_all("/^\s{4}\[(.+?)\] \=\> /m", $in, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
$pos = array();
$previous_key = '';
$in_length = strlen($in);
// store the following in $pos:
// array with key = key of the parsed array's item
// value = array(start position in $in, $end position in $in)
foreach ($matches as $match) {
$key = $match[1][0];
$start = $match[0][1] + strlen($match[0][0]);
$pos[$key] = array($start, $in_length);
if ($previous_key != '') $pos[$previous_key][1] = $match[0][1] - 1;
$previous_key = $key;
}
$ret = array();
foreach ($pos as $key => $where) {
// recursively see if the parsed out value is an array too
$ret[$key] = print_r_reverse(substr($in, $where[0], $where[1] - $where[0]));
}
return $ret;
}
}
?>
I have not tested the above function.

Categories