PHP: Get array values based on conditions - php

I've been puzzling a lot with getting the correct values based on some conditions. First, let's look at what PHP's function var_dump() returned. This is just the important part in adjustment to the data I look for. Check the whole json object here.
array (size=3)
0 =>
array (size=12)
'inputs' =>
array (size=2)
0 =>
array (size=3)
'prev_out' =>
array (size=7)
'addr' => string '1AvY95SQqtWy6MKWZbE3Xnqant9F3whfPH' (length=34)
'value' => int 1583375
1 =>
array (size=3)
'prev_out' =>
array (size=7)
'addr' => string '1KEUVc2TxDh1VAcvrS5p3PtJHcRwzrvin1' (length=34)
'value' => int 150000
'out' =>
array (size=2)
0 =>
array (size=7)
'addr' => string '1Djp9h8mR3qqRz6v54nx265b8jZuqYNQ8j' (length=34)
'value' => int 1046166
1 =>
array (size=7)
'addr' => string '13W7N4NFwpTkYnHuVABcQfdrvDyszDqwkr' (length=34)
'value' => int 677209
What you just saw was the output of $data['txs']. The outer array is a list of transactions. Within each, the details are specified. The length of the "inputs" and "out" can change! I want to get the value of each transaction ($data['txs'][index of transaction]['out']['value']) that meets the following criteria:
The value of the "out" transaction should be bigger than zero.
The address of the "out" transaction should be equal to $address.
$address is not in the "inputs" transaction. E.g: $address can not be in the array of all ['inputs'][count(inputs)]['inputs']['prev_out']['addr'].
Here is my last attempt at solving this. The problem is that $result stays empty, even though the address 13W7N4NFwpTkYnHuVABcQfdrvDyszDqwkr is there and the result should be 677209.
$i = 0;
$txresult = array();
foreach($data['txs'] as $ct => $cv) {
$index = count($data['txs'][$i]['inputs']) - 1;
$addressindex = array();
for($testindex = 0; $testindex < $index; $testindex++) {
$addressindex[] = $data['txs'][$i]['inputs'][$index]['prev_out']['addr'];
}
$counter = count($data['txs'][$i]['out']) - 1;
for($count = 0; $count < $counter; $count++) {
if ($data['txs'][$i]['out'][$count]['value'] > 0 && $data['txs'][$i]['out'][$count]['addr'] == $address && !in_array($address, $addressindex)) {
$result = $data['txs'][$i]['out'][$count]['value'];
}
}
$i++;
}
Remember I cut the scope of the code, so it's possible some suggestions that require too much change may not work. I will do my best to respond to your questions asap.

Figured it out on my own terms. #Wrikken was instrumental to come to a conclusion.
The solution was pretty easy. Only two things:
$i++ shouldn't be in any of the for-loops, so I put it at the end of the foreach loop.
I had to unset $addressindex, $counter and $index.

Related

SQL/PHP sort fields from a form to make insert

I've got a form which users can add new rows by clicking on a button and automatically, it adds +1 on the field's name.
So for example, I've got my train_id_1, train_type_1 and my user wants to add a new one, so now I've got train_id_2 and train_type_2.
In order to save this in my database, I would like to sort and seperate train_type_1 / train_type_2... to make a foreach and then to save in my database.
So, the var_dump of my $_POST looks like :
array (size=60)
'train_id_1' => string ' 07:36' (length=6)
'train_type_1' => string ' -Z' (length=3)
'user_id_1' => string 'CPN' (length=3)
'event_criter_1' =>
array (size=3)
0 => string 'test' (length=4)
1 => string '234' (length=3)
2 => string '532' (length=3)
'train_id_2' => string ' 08:32' (length=6)
'train_type_2' => string ' -X' (length=3)
'user_id_2' => string 'CPN' (length=3)
'event_criter_2' =>
array (size=3)
0 => string 'TESTG' (length=5)
1 => string 'GGG' (length=3)
2 => string 'AETG' (length=4)
'train_id_3' => string ' 08:36' (length=6)
'train_type_3' => string ' -Z' (length=3)
'user_id_3' => string 'CPN' (length=3)
'event_criter_3' =>
array (size=1)
0 => string '' (length=0)
'train_id_4' => string ' 09:04' (length=6)
'train_type_4' => string ' -X' (length=3)
'user_id_4' => string 'CPN' (length=3)
'event_criter_4' =>
array (size=1)
0 => string '' (length=0)
Do you know how I can make abcd_1 separate from abcd_2 to make my foreach (or another solution) ?
Thank you!
Loop through your array, matching _1 and insert the posted elements as one row. Then increment and match _2 etc..
$postedElements = $_POST;
$elementsPerRow = 4;
$numRows = count($postedElements)/$elementsPerRow;
// loop through the number of 'rows' to insert
for($i=1;$i<=$numRows;$i++){
// Build an array to store matched elements to insert
$elementsToInsert = array();
//process the complete _POST array each time...
foreach($postedElements as $name => $value){
// ...get the 'row' (the bit after the underscore)...
//list($value,$row) = explode('_',$name); // doesn't work for 2 underscores..
$row = end(explode($name)); // This will
if($row == $i){
// ...and add elements that match to an insert array
// $elementsToInsert[] = $name;
$elementsToInsert[$name] = $value;
}
}
// insert $elementsToInsert into DB
}
I think, at first You need to have a amount of records in array through count($arr). Then use usual for loop:
//output of field names
for ($i = 0; $i < count($arr); $i++){
//Work with array
}
Make a new array.
Then add a data from loop into new array.
I think it could help You.
And by which reason You need to sort them?

Filter a PHP array so that only unique records remain

I have this PHP array:
array (size=9753)
0 =>
array (size=3)
'brand' => string 'Brand #1' (length=8)
'name' => string 'Customer #13' (length=12)
'total' => string '93.00' (length=5)
1 =>
array (size=3)
'brand' => string 'Brand #1' (length=8)
'name' => string 'Customer #23' (length=12)
'total' => string '77.00' (length=5)
2 =>
array (size=3)
'brand' => string 'Brand #1' (length=8)
'name' => string 'Customer #32' (length=12)
'total' => string '98.00' (length=5)
...
I want to filter it so that only the record with the highest total value remains for every unique brand (there are 100 brands, in total). The result of the operation for this sample should be:
0 =>
array (size=3)
'brand' => string 'Brand #1' (length=8)
'name' => string 'Customer #32' (length=12)
'total' => string '98.00' (length=5)
...
as Brand #1 has the highest total
This is a matter of iterating over the whole array and leaving only one record for each Brand - the one with the highest total.
I've been trying my best, but didn't manage to achieve this. The code that I came up with is this:
$c = count($ordersData);
for($i=1; $i<$c; $i++) {
if($ordersData[$i]['brand'] == $ordersData[$i-1]['brand']
&& $ordersData[$i]['total'] > $ordersData[$i-1]['total']) {
unset($ordersData[$i-1]);
}
}
, but it does not remove all records that should be removed.
Suggestions are much appreciated.
So it seems like your best option is definitely to loop over all the records in $ordersData, as you've done. However, your logic is a bit wacky, and only compares the ordersdata total to the total of the previous order checked.
Instead, you'll likely want to start a new array, and add/overwrite values based on the brand name. Something like this, perhaps:
<?php
$results = array();
foreach($ordersData as $order) {
$brand = $order['brand'];
$total = $order['total'];
// If an order of this brand has already been tracked
if(array_key_exists($brand, $results)) {
// and the total of the current order is greater than what we have recorded
if($results[$brand]['total'] < $total) {
// Then let's replace it!
$results[$brand] = $order;
}
} else {
// Never added this brand before? Add it then
$results[$brand] = $order;
}
}
You can sort the array on total, ascending, then create a temp array indexed on brand (so that the key will get overwritten with later(higher) values), then use array_values to get numerically indexed array:
usort($array, function($a, $b) {
return $b['total'] - $b['total'];
});
$temp=[];
foreach($array as $element) $temp[$element['brand']]=$element;
$out = array_values($temp);
I've also come up with another method. I'm pasting it here just for reference (this is my initial attempt, improved).
$c = count($ordersData);
// Let's iterate through the whole array
for($i=0; $i<$c; $i++) {
// Save the current brand being checked
$currentBrand = $ordersData[$i]['brand'];
// If we can still check against the next record and the this is still the same brand..
if (key_exists($i+1, $ordersData) && $ordersData[$i]['brand'] == $ordersData[$i+1]['brand']) {
// If the next order value for the current brand is higher..
if ( $ordersData[$i]['total'] < $ordersData[$i+1]['total'] ) {
//Let's save/overwrite the higher order for the current brand
$results[$currentBrand] = $ordersData[$i+1];
}
}
}

How to get next value in a multidimensional array

I am trying to produce a HTML list grouped by "groupName" from the array below.
array (size=30)
0 =>
array (size=4)
'groupOrder' => string '1' (length=1)
'groupName' => string 'Class' (length=11)
'txt' => string '............' (length=32)
'ID' => string '6' (length=1)
1 =>
array (size=4)
'groupOrder' => string '1' (length=1)
'groupName' => string 'Size' (length=11)
'txt' => string '..................' (length=34)
'ID' => string '6' (length=1)
2 =>
...
So I'd like produce something like this pseudo list:
groupName
txt
txt
txt
next GroupName
txt
txt
...
So my code looks like this
foreach ($datafeed as $val => $row) {
if (($datafeed[$val]['groupName']) == next($datafeed[$val]['groupName'])) {
//same group - do nothing
} else {
echo $datafeed[$val]['groupName'];
}
echo "<li>".$row['txt']. "</li>";
}
But I'm getting errors about "next() expects parameter 1 to be array, string given".
I've tried all sorts of different syntax, but I'm not making much progress. How do I compare two values in a nested array?
You misinterpreted the meaning of the function next(): you cannot query it for an array element. It manipulates the internal array pointer tied with the array itself, not with some its element. From the PHP documentation:
Every array has an internal pointer to its "current" element, which is initialized to the first element inserted into the array.
and see also a description of next.
Since the foreach loop crucially depends on the value of the array pointer, messing with the array pointer will ruin the loop: you probably see every second element in the loop, because at every iteration once next() is called by your foreach loop and then once by yourself.
The simplest thing for you is probably to use the old good for loop:
for ($i = 0; $i < length ($array); $i++)
{
if ($i == 0 || $array[$i] != $array[$i - 1])
echo "New group!\n";
echo $array[$i];
}
This doesn't answer your question directly, but you'd be better off restructuring your array so that they're grouped, and you don't need to perform any logic within the loop to check the groupName. Currently, you're relying on the next groupName to match the current groupName, but if they're not sequential, they won't be grouped.
You could do something like this:
$output = array();
foreach ($datafeed as $feed) {
$output[$feed['groupName']][] = $feed;
}
Here's a demo
You should not use next inside a foreach loop anyway, since you'll get conflicting array pointer movements. Simply store the last value:
$last = null;
foreach (...) {
if ($last != $row['current']) {
// new group
}
$last = $row['current'];
...
}

Intersection of two multidimensional arrays in PHP

I am having the following array defined:
array(
'name'=>'Blue',
'age'=>'0',
'skin'=>array(
'White Skin','Tanned Skin'
),
'eye'=>array(
'Black','Brown','Honey'
),
'personality'=>array(
'Intelligent','Warm','Trustworthy','Sweet'
),
'ocassion'=>array(
'Every day wear','Celebrations','Restaurant Dinner','Feasts','Visiting friends'
),
'hair'=>'All Colors',
'style'=>array(
'Loved to be admired','Center of attention'
),
'description'=>'Blue lens are perfect for any..'
);
and I am trying to find the number of matches, from an HTML form into this array. A possible return from the HTML form, in array format would be:
Array
(
[age] => 16
[skin] => Tanned Skin
[eye] => Brown
[personality] => Array
(
[0] => Intelligent
[1] => Warm
[2] => Trustworthy
)
[ocassion] => Weddings
[hair] => Dark Brown
[style] => Array
(
[0] => Style Queen
[1] => Testing val
)
)
I have tried iterating trough each key of the first array, but failed to achieve what I want, and also I've tried using the function array_intersect_assoc($stack,$search) but it seems it won't find the exact matches because the $search array ( second example ) has some key=>value pairs that are of type string, and it cannot match any occurrence into the first array because the value is actually an array, and not a string.
Can someone point me an idea or can let me know what's best to do over here?
I have tried a lot of things in the last 3 hours but no success.
Ok, so how about this.
The source data:
$demands = array(
'name'=>'Blue',
'age'=>'0',
'skin'=>array(
'White Skin','Tanned Skin'
),
'eye'=>array(
'Black','Brown','Honey'
),
'personality'=>array(
'Intelligent','Warm','Trustworthy','Sweet'
),
'ocassion'=>array(
'Every day wear','Celebrations','Restaurant Dinner','Feasts','Visiting friends'
),
'hair'=>'All Colors',
'style'=>array(
'Loved to be admired','Center of attention'
),
'description'=>'Blue lens are perfect for any..'
);
$possible_match = array(
'age'=>'16',
'skin'=>'Tanned Skin',
'eye'=>'Brown',
'personality'=>array(
'Intelligent','Warm','Trustworthy'
),
'ocassion'=>array(
'Weddings'
),
'hair'=>'Dark Brown',
'style'=>array(
'Style Queen','Testing value'
)
);
And the match-making algorithm:
$result = array();
$count_matches = 0;
// Go through all the demands
foreach ($demands as $key => $value){
// If there's a matching key in the possible match array
if (isset($possible_match[$key])){
// If there are more demanded values
if (is_array($value)){
// Let all demanded values be lowercase
$value = array_map('strtolower', $value);
// If there are more possible matching values
if (is_array($possible_match[$key])){
// Let all possibly matching values be lowercase, too
$possible_match[$key] = array_map('strtolower', $possible_match[$key]);
// And then do the intersect.
$intersect = array_intersect($value, $possible_match[$key]);
if ($intersect){
// If that intersect is not empty, add that to the resulting array
$result[$key] = $intersect;
$count_matches += count($intersect);
};
} else {
// If there's only one possible matching value, search that
// value in the demaned array
if (in_array(strtolower($possible_match[$key]), $value, true)){
// And add it to the results
$result[$key][] = strtolower($possible_match[$key]);
$count_matches++;
}
}
} else {
if (is_array($possible_match[$key])){
// If there are more possible matching values but the demand is a string,
// find that string in those possible values
$possible_match[$key] = array_map('strtolower', $possible_match[$key]);
if (in_array(strtolower($value), $possible_match[$key], true)){
// And add it to the results
$result[$key] = $value;
$count_matches++;
}
} else {
// If the demanded value is only one (= it's a string and not an array)
// and the possible match is also a string, do a lowercase compare
// + if there's a word "all" in the demanded value, pass it at all times ;D
if (strtolower($possible_match[$key]) == strtolower($value)
|| stripos($value, "all") !== false){
// And add it to the resulting array
$result[$key] = strtolower($value);
$count_matches++;
}
}
}
}
}
var_dump ($result);
var_dump ($count_matches);
There may be some opportunities for optimizing, but the basic idea should be there :)
The result:
array (size=4)
'skin' =>
array (size=1)
0 => string 'tanned skin' (length=11)
'eye' =>
array (size=1)
0 => string 'brown' (length=5)
'personality' =>
array (size=3)
0 => string 'intelligent' (length=11)
1 => string 'warm' (length=4)
2 => string 'trustworthy' (length=11)
'hair' => string 'all colors' (length=10)
Plus the count, if you'd like:
int 6

Accessing an array inside of an array

When trying to access an array inside an array, only NULL is output.
My Code:
$aStats = array();
$aStats['hd'] = array();
$aStats['hd'][] = array
(
'dev' => $device,
'total' => $total,
'used' => $used,
'free' => $free,
'used_perc' => $used_perc,
'mount' => $folder
);
echo $aStats['hd']['free'];
When using json_encode, the values are displayed correctly:
die( json_encode( $aStats ) );
Where is my mistake?
Replace these lines:
$aStats['hd'] = array();
$aStats['hd'][] = array
With this:
$aStats['hd'] = array
You appear to be accessing your array ($aStats['hd']['free'];) as if the value of hd is an associated array, but using [] creates a new integer index in the array, and stores the value in that index. Joe Walker's answer shows what happens instead, that you have an associative array pointing to an indexed array pointing to another associative array, rather than the associative to associative array you suggest you're trying to use in your echo statement.
This is a practical tip that will let you find out where is the issue easly, all you need to do is:
var_dump($aStats);
This will output:
array (size=1)
'hd' =>
array (size=1)
0 =>
array (size=6)
'dev' => string 'SomeDevice' (length=10)
'total' => string '10000' (length=5)
'used' => boolean true
'free' => boolean false
'used_perc' => string 'none' (length=4)
'mount' => string '/some/directory/here/' (length=21)
Now you know you can access this element using
$aStats['hd'][0]['free'];
This will return null in your question because your variables are not yet initialized, but I guess you do have them initialized in your code, hope this helps.

Categories