Counting multiple values from a query - php

I'm getting an array of this type from the database: (I can't change the type of data received, as it comes from an outside source)
Array
(
[0] => Es\Result Object
(
[_hit:protected] => Array
(
[_index] => website
[_type] => structure
[_id] => 8
[_score] => 0.625
[_source] => Array
(
[name] => Test1
[locality] => Array
(
[locality] => Bologna
[sign] => BO
[province] => Array
(
[province] => Bologna
[region] => Array
(
[region] => Emilia Romagna
)
)
)
)
)
)
[1] => Elastica\Result Object
(
[_hit:protected] => Array
(
[_index] => website
[_type] => structure
[_id] => 6
[_score] => 0.625
[_source] => Array
(
[name] => Test2
[locality] => Array
(
[locality] => Bologna
[sign] => BO
[province] => Array
(
[province] => Bologna
[region] => Array
(
[region] => Emilia Romagna
)
)
)
)
)
)
......
I enter into a json object value of "locality" and count how many "locality" are equal, for example:
foreach ($results as $result) {
$source = $result->getSource();
$locality = $source['locality']['locality'];
$dataLocality[] = array(
'type' => 'locality',
'label' => $locality,
'count' => 1, //How to increase the count here?
);
}
I tried to put everything in a loop but I can't count the values ​​correctly.
Is there a way to do this?
EDIT
This should be the result that I get:
let's say I get the array has 3 "locality":
2 "foo"
1 "bar"
$dataLocality =
Array
(
[0] => Array
(
[type] => 'locality'
[locality] => 'foo'
[count] => 2
)
[1] => Array
(
[type] => 'locality'
[locality] => 'bar'
[count] => 1
)
)

Does the value of $locality exist in the array? If no, then store it with a count of 1. If yes, then add 1 to the count.
foreach ($results as $result) {
$source = $result->getSource();
$locality = $source['locality']['locality'];
// Manually specify the array key. This makes life much easier down the road,
// especially when you need to find items in the array.
if ( !isset($dataLocality[$locality]) ) {
$dataLocality[$locality] = array('type' => 'locality',
'label' => $locality,
'count' => 1);
} else {
$dataLocality[$locality]['count'] += 1;
}
}

Declare an array (say $dataLocality) outside your foreach loop. In each loop you search for an existant locality in $datalocality (if $result is in $dataLocality). If there is one, you increment the counter by $dataLocality[$indexOfFounding]['count']++.
This off course requires the adding of your array of 'type', 'label' and 'count' if you don't find any locality in $dataLocality.
After the foreach loop you can go through your array and output or do anything with your results.

If you are needing the count of locality array then make use of count Try:
foreach ($results as $result) {
$source = $result->getSource();
$locality = $source['locality']['locality'];
$dataLocality[] = array(
'type' => 'locality',
'label' => $locality,
'count' => count($source['locality']), //get locality array count
);
}

Thanks to #Dave's reply I solved the problem, but since I could not have named keys, I added outside the loop:
$dataLocality = array_values($dataLocality);
so the complete code to solve the problem, but on occasions someone had a problem similar to mine is:
foreach ($results as $result) {
$source = $result->getSource();
if(!isset($dataLocality[$locality = $source['locality']['locality']])) {
$dataLocality[$locality] = array(
'type' => 'locality',
'label' => $locality,
'count' => 1,
);
} else {
$dataLocality[$locality]['count']++;
}
}
$dataLocality = array_values($dataLocality);

Related

How to get value by key from multidimensional array from an object attribute as number in PHP

How to get value by key from the multidimensional array in PHP
We Get TradeID in foreach loop
We get TradeID by Loop one by one
stdClass Object
(
[0] =>
[1] => 1
[2] => Array
(
[0] => Array
(
[TradeID] => 15950315
[Price] => 0.00000170
[Type] => buy
[Amount] => 712.85989430
[Total] => 0.00121368
[Time] => 1535337908
)
[1] => Array
(
[TradeID] => 15908375
[Price] => 0.00000300
[Type] => buy
[Amount] => 574.71264368
[Total] => 0.00172673
[Time] => 1535022882
)
)
)
You need to use foreach twice.
PHP Code:
/* Generating structure */
$rawdata = array(
'',
1,
array(
array(
'TradeID' => 15950315,
'Price' => 0.00000170,
'Type' => 'buy',
'Amount' => 712.85989430,
'Total' => 0.00121368,
'Time' => 1535337908,
),
array(
'TradeID' => 15908375,
'Price' => 0.00000300,
'Type' => 'buy',
'Amount' => 574.71264368,
'Total' => 0.00172673,
'Time' => 1535022882,
)
)
);
$data = (object)$rawdata;
print_r($data);// same output as shown in the question
/** Getting TradeID */
foreach ($data as $key => $value) {
if (is_array($value)) {
foreach ($value as $tradeKey => $tradevalue) {
echo $tradevalue['TradeID'].'<br/>';
}
}
}
Please check output at: https://3v4l.org/d3KbN
Considering the $object variable would be the object you see, and only the first layer is an object, you can cast to an array using the notation (array) and continue the logic that you probably know already:
$array = (array) $object;
foreach ($array['2'] as $item) {
echo $item['TradeID'];
}
Sorry for the previous answer, this one is fixed and tested here: https://3v4l.org/LOYtp

PHP: create 2 dimensional array from multidimensional array with value as key

I try to create a new array from an complex array.
If there's no easy solution, every hint would help to search more successful.
I have this complex array (shortened a lot) and want to build a new 2 dimensional array:
array (
[key1] => value1
[key2] => value2
[category] => array (
[key3] => value3
[key4] => array (
[small] => value6
[large] => value7
)
[items] => array (
[0] => array (
[aTag] => #PU2RRL
[name] => 3PL
[position] => 25
[versions] => array (
[0] => array (
[bTag] => #KF67RL
[color] => blue
[id] => 001
)
[1] => array (
[bTag] => #Z8TR4
[color] => red
[id] => 002
)
)
)
[1] => array (
...
This is the array I want to create:
array(
[001] => array (
[aTag] => #PU2RRL
[name] => 3PL
[position] => 25
[bTag] => #KF67RL
[color] => blue
)
[002] => array (
[aTag] => #PU2RRL
[name] => 3PL
[position] => 25
[bTag] => #Z8TR4
[color] => blue))
With ID as key and this values:
$itemAll = array(
$array[category][items][0][versions][0][id] => array(
"aTag" => $array[category][items][0][aTag],
"name" => $array[category][items][0][name],
"position" => $array[category][items][0][position],
"bTag" => $array[category][items][0][versions][0][bTag],
"color" => $array[category][items][0][versions][0][color],
)
);
I have no clue how to create this array with foreach loops for "items" and versions with the ID as primary key, any hints?
EDIT: huge thanks to #DeeDuu! Because I had multiple items I added another foreach:
$new_array = array();
// i have multiple items, so I removed [0]:
$items = $array["category"]["items"];
// added another foreach
foreach ($items as $item) {
// changed $items to $item
$shared_properties = array(
"aTag" => $item["aTag"],
"name" => $item["name"],
"position" => $item["position"]
);
// changed $items to $item
foreach ($item["versions"] as $version) {
$specific_properties = array(
"bTag" => $version["bTag"],
"color" => $version["color"]
);
$new_entry = array_merge(
$shared_properties,
$specific_properties
);
$new_array[$version["id"]] = $new_entry; }}
If I understand correctly what you want, something like the following should work.
// This is the target array where we will save the recombinated data
$new_array = array();
// Store the relevant subarray in a new variable;
// This makes the subsequent code shorter
$items = $array["category"]["items"][0];
// This gives the data that will be common to all the new entries,
// for all versions seem to share aTag, name and position
$shared_properties = array(
"aTag" => $items["aTag"],
"name" => $items["name"],
"position" => $items["position"]
);
// Alright, let's loop over the versions
foreach ($items["versions"] as $version) {
// Another array for the data that is specific
// to the version we're currently looking at
$specific_properties = array(
"bTag" => $version["bTag"],
"color" => $version["color"]
);
// The new entry is a combination of the shared and the
// specific properties; array_merge will do that for us
$new_entry = array_merge(
$shared_properties,
$specific_properties
);
// Now add to the new array
$new_array[$version["id"]] = $new_entry;
}

How do I remove one array from another in php?

I have the following arrays in PHP:
print_r($employees) =
Array
(
[0] => Array
(
[p_id] => T29083999
[name] => Robert Plaxo
)
[1] => Array
(
[p_id] => T29083388
[name] => Yvan Sergei
)
[2] => Array
(
[p_id] => T21083911
[name] => Rhonda Saunders
)
[3] => Array
(
[p_id] => H02910382
[name] => Miguel Mercado
)
)
then this array:
print_r($record) =
Array
(
[0] => Array
(
[c_id] => 1
[section] => 1061
[term] => 201631
[p_id] => T29083388
[c_date] => 2016-04-01 09:14:00
)
)
I want to remove the array element from $employees that matches the p_id of $record. Array $record may have multiple entries like the one shown. If so, any p_id in $record must be removed from $employees.
I tried:
foreach ($employees as $k => $e) {
foreach ($record as $r) {
if ($e['p_id']==$r['p_id']) {
echo "found it!";
// if I uncomment the next line, it crashes! (500 server error)
// unset $employees[$k];
}
}
}
I just want to remove any element from $employees that has any employee that matches any record in $record with that employee id.
You were almost there; just needed parens around your unset()
I also took the liberty to change some of your variable names as single character variable names bother me.
$employees[] = [
'p_id' => 'T29083999',
'name' => 'Robert Plaxo',
];
$employees[] = [
'p_id' => 'T29083388',
'name' => 'Yvan Sergei',
];
$employees[] = [
'p_id' => 'T21083911',
'name' => 'Rhonda Saunders',
];
$employees[] = [
'p_id' => 'H02910382',
'name' => 'Miguel Mercado',
];
$records[] = [
'c_id' => '1',
'section' => '1061',
'term' => '201631',
'p_id' => 'T29083388',
'c_date' => '2016-04-01 09:14:00',
];
foreach ($employees as $key => $employee) {
foreach ($records as $record) {
if ($employee['p_id'] == $record['p_id']) {
echo "found it!";
unset($employees[$key]);
}
}
}
echo "<pre>";
print_r($employees);
Outputs
found it!
Array
(
[0] => Array
(
[p_id] => T29083999
[name] => Robert Plaxo
)
[2] => Array
(
[p_id] => T21083911
[name] => Rhonda Saunders
)
[3] => Array
(
[p_id] => H02910382
[name] => Miguel Mercado
)
)
The short solution using array_column and array_filter functions. It will also fit your requirement "Array $record may have multiple entries":
$p_ids = array_column($record, "p_id");
$employees = array_filter($employees, function($v) use($p_ids){
return !in_array($v["p_id"], $p_ids);
});
print_r($employees);
The output:
Array
(
[0] => Array
(
[p_id] => T29083999
[name] => Robert Plaxo
)
[2] => Array
(
[p_id] => T21083911
[name] => Rhonda Saunders
)
[3] => Array
(
[p_id] => H02910382
[name] => Miguel Mercado
)
)

php - nav/subnav structure from array

I'm trying to create a "plugin" like script for adding to a "menu array".... I'll go straight in..
Lets say I initiate a nav item like so:
$sections->add_section('dashboard');
$DashBoardSection = $sections->load_section('dashboard');
$DashBoardSection->set_role(NULL);
$DashBoardSection->set_nav_item(array(
'identifier' => 'dashboard',
'text' => 'Dashboard',
'url' => NULL,
'position' => NULL
));
starts off by creating a new section and the getting the instance of.
We are then setting a "role" in which we will test against to see if the user is authenticated as being verified to view.
The set nav item simply stores the array. identifier is a reference to the item ( its for when we want to add sub items), all standard apart from "position" which states where it is to sit in the nav i.e. NULL is top level, array('topnav','subnav') will be topnav->subnav->dashboard.
as a test, this could be stored as follows:
Array
(
[0] => Array
(
[identifier] => dashboard
[text] => Dashboard
[url] =>
[position] =>
)
[1] => Array
(
[identifier] => dashboard2
[text] => Dashboard2
[url] =>
[position] => Array
(
[0] => dashboard
)
)
)
my question being how I turn that into the following structure:
Array
(
[0] => Array
(
[identifier] => dashboard
[text] => Dashboard
[url] =>
[position] =>
[children] => Array
(
[0] => Array
(
[identifier] => dashboard2
[text] => Dashboard2
[url] =>
)
)
)
)
pulling my hair out over this one, any help would be very much appreciated.
regards
I currently have
public function build_navigation( $role ){
$role = (int)$role;
$nav = array();
foreach( $this->sections as $section ) {
if( $section->get_role() === NULL || $section->get_role() === $role ) {
$nav_array = $section->get_nav();
foreach( $nav_array as $key => $nav_item ) {
if( $nav_item['position'] === NULL ) {
$nav[$nav_item['identifier']] = $nav_item;
}elseif( is_array( $nav_item['position'] ) ){
#...#
}
}
}
}
return $nav;
}
EDIT
Imagine this is the array given (it can be in any order)
Array
(
[0] => Array
(
[identifier] => dashboard_child2
[text] => Dashboard Child 2
[url] =>
[position] => Array
(
[0] => dashboard
)
)
[1] => Array
(
[identifier] => dashboard_child_child_1
[text] => Dashboard Child Child 1
[url] =>
[position] => Array
(
[0] => dashboard
[1] => dashboard_child1
)
)
[2] => Array
(
[identifier] => dashboard_child1
[text] => Dashboard Child 1
[url] =>
[position] => Array
(
[0] => dashboard
)
)
[3] => Array
(
[identifier] => dashboard
[text] => Dashboard
[url] =>
[position] =>
)
[4] => Array
(
[identifier] => dashboard2
[text] => Dashboard2
[url] =>
[position] => Array
(
[0] => dashboard
)
)
)
Which needs to be formatted as:
Array
(
[dashboard] => Array
(
[text] => Dashboard
[url] =>
[children] => Array
(
[dashboard_child2] => Array
(
[text] => Dashboard Child 2
[url] =>
)
[dashboard_child1] => Array
(
[text] => Dashboard Child 1
[url] =>
[children] => Array
(
[dashboard_child_child_1] => Array
(
[text] => Dashboard Child Child 1
[url] =>
)
)
)
[dashboard2] => Array
(
[text] => Dashboard2
[url] =>
)
)
)
)
Here's my take on the problem, solved with recursion.
You can use multiple positions (i guess this is why it's an array), it will ignore missing positions if at least on of the positions is found, but will complain if every position is missing.
function translate($in) {
$out = array();
// first pass, move root nodes to output
foreach ($in as $k => $row) {
if (!$row['position']) {
$out[$row['identifier']] = $row;
unset($in[$k]);
}
}
// while we have input
do {
$elements_placed = 0;
// step trough input
foreach ($in as $row_index => $row) {
foreach ($row['position'] as $pos) {
// build context for the node placing
$data = array(
'row' => $row,
'in' => &$in,
'row_index' => $row_index,
'elements_placed' => &$elements_placed,
'pos' => $pos,
);
// kick of recursion
walker($out, $data);
}
}
} while ($elements_placed != 0);
if (count($in)) {
trigger_error("Error in user data, can't place every item");
}
return $out;
}
function walker(&$out, $data) {
foreach ($out as &$row) {
// it looks like a node array
if (is_array($row) && isset($row['identifier'])) {
// if it has children recurse in there too
if (isset($row['children'])) {
walker($row['children'], $data);
}
// it looks like a node array that we are looking for place the row
if ($row['identifier'] == $data['pos']) {
if (!isset($row['children'])) {
$row['children'] = array($data['row']['identifier'] => $data['row']);
} else {
$row['children'][$data['row']['identifier']] = $data['row'];
}
// report back to the solver that we found a place
++$data['elements_placed'];
// remove the row from the $in array
unset($data['in'][$data['row_index']]);
}
}
}
}
$in = array (
array (
'identifier' => 'secondlevelchild2',
'text' => 'secondlevelchild2',
'url' => '',
'position' => array (
'dashboard2',
),
),
array (
'identifier' => 'secondlevelchild',
'text' => 'secondlevelchild',
'url' => '',
'position' => array (
'dashboard2',
),
),
array (
'identifier' => 'dashboard',
'text' => 'Dashboard',
'url' => '',
'position' => '',
),
array (
'identifier' => 'dashboard2',
'text' => 'Dashboard2',
'url' => '',
'position' => array (
'dashboard', 'home',
),
),
array (
'identifier' => 'thirdlevelchild',
'text' => 'thirdlevelchild',
'url' => '',
'position' => array (
'secondlevelchild2',
),
),
);
$out = translate($in);
var_export($out);
In it's current form it doesn't remove the identifier or position keys from the node arrays once they are placed.
You need a temporary array that maps the identifier to the children array of it so that you can add it there.
If I see that right, you have something like that already here when you add the parent:
$nav[$nav_item['identifier']] = $nav_item;
Edit: Adding the parent needs some caution as pointed out in the comment:
$node = &$nav[$nav_item['identifier']];
$children = isset($node['children']) ? $node['children'] : array();
$node = $nav_item;
$node['children'] = $children;
unset($node);
Just add to the children then:
foreach($nav_item['position'] as $identifier)
{
$nav[$identifier]['children'][] = $nav_item;
}
Also you could use objects, not arrays, so that you do not duplicate data that much (or you can change it later), however, just thinking, this must not be necessary to solve your problem so probably something for later.

Highlighting array values

I have an array of statistics on racing dogs. I need to highlight the maximum and minimum values in each element by adding another element. Let me explain.
Example of array
Array
(
[1] => Array
(
[fast_calc_7] => 31.06
[av_calc_7] => 25.03
)
[2] => Array
(
[fast_calc_7] => 16.74
[av_calc_7] => 18.06
)
[3] => Array
(
[fast_calc_7] => 30.93
[av_calc_7] => 31.06
)
[4] => Array
(
[fast_calc_7] => 29.01
[av_calc_7] => 25.08
)
[5] => Array
(
[fast_calc_7] => 30.72
[av_calc_7] => 31.02
)
[6] => Array
(
[fast_calc_7] => 31.16
[av_calc_7] => 36.02
)
)
Example of resulting array
I need to compare these values and add another element specifying if it is the highest of lowest value. For example, it should generate an array such as the following.
Array
(
[1] => Array
(
[fast_calc_7] => 31.06
[av_calc_7] => 25.03
)
[2] => Array
(
[fast_calc_7] => 16.74
[fast_calc_7_lowest] => TRUE
[av_calc_7] => 18.06
[av_calc_7_lowest] => TRUE
)
[3] => Array
(
[fast_calc_7] => 30.93
[av_calc_7] => 37.06
[av_calc_7_highest] => TRUE
)
[4] => Array
(
[fast_calc_7] => 29.01
[av_calc_7] => 25.08
)
[5] => Array
(
[fast_calc_7] => 30.72
[av_calc_7] => 31.02
)
[6] => Array
(
[fast_calc_7] => 31.16
[fast_calc_7_highest] => TRUE
[av_calc_7] => 36.02
)
)
I'm sure there is a really simple way to do this. The more I have to iterate through arrays, the slower my application gets!
Thanks guys.
EDIT: How data is sourced
JSON array gathered from greyhound website for each dogs "race history"
JSON array is processed to form a nice array for each dogs history with the data for example the time for each race, finishing position etc.
This data is then calculated for each dog to find the fastest time, average time and other data. This is the array above. (Each array is a different dog).
At this point, I need the array processed to add in the highlighting elements.
There isn't much to it. You need to loop over the array, maintaining variables with the indexes of the high/low elements so far for each attribute. After the loop, access those elements and add your extra data.
$lowAverage = $highAverage = array('index' => null, 'value' => 0);
$lowFast = $highFast = array('index' => null, 'value' => 0);
foreach($dogs as $index => $data) {
if($lowAverage['index'] == null || $data['av_calc_7'] < $lowAverage['value']) {
$lowAverage = array('index' => $index, 'value' => $data['av_calc_7']);
}
if($highAverage['index'] == null || $data['av_calc_7'] > $highAverage['value']) {
$highAverage = array('index' => $index, 'value' => $data['av_calc_7']);
}
// same for $lowFast, $highFast
}
if($lowAverage['index'] != null) {
$dogs[$lowAverage['index']]['av_calc_7_lowest'] = true;
}
// same for the other 3 values

Categories