php explode and calculating the sum of strings - php

i have an array in my db
example : 1:11 1,12 2,13 3,14 4,15 5,16
i don't need 1:11 in the array
and i don't need the (12,13,14,15,16)
i just need to explode them and get only 1,2,3,4,5 in the array
and then i need to calculate the sum of them
$tr_arr = $this->data['troops_intrap_num']; // this is the above array from db
$explode_arr = explode(" ", $tr_arr); // exploding the array
print_r($explode_arr); // this will print the array and it should look like this
Aray
(
[0] => 1:11
[1] => 1,12
[2] => 2,13
[3] => 3,14
[4] => 4,15
[5] => 5,16
[6] => 0
)
i need to make something like that after exploding
Aray
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
// and then i need to calculate the sum of the numbers 1+2+3+4+5 = 15 and echo it as 15
the question is what should i do to remove the first string 1:11 and the last one witch is 0 and then remove the (12-13-14-15-16)
so the 1,2,3,4,5 only will be left and then i wan't to calculate the sum of the them
help me

You could simply unset the first value using unset(). The last one can be done in the same manner but this isn't neccasary since array_sum() will simply add zero.
$array = array(
'1:14:aaaa',
'1.5',
'3',
'4.5',
'1.5',
'0',
);
// Unset the first value
unset($array[0]);
// Calculate total amount
$total = array_sum($array);
Edit
Because your array has numbers with a comma as decimal character, you will first need to convert each value.
$array = array_map(function($val) {
// Without removing decimals
// return floatval(str_replace(',', '.', str_replace('.', '', $val)));
// Remove decimals as well
return floor(floatval(str_replace(',', '.', str_replace('.', '', $val))));
}, $array);
Complete answer
$array = array(
'1:11',
'2,12',
'3,13',
'4,14',
'5,15',
'0',
);
// Unset the first value
unset($array[0]);
$array = array_map(function($val) {
// Remove decimals as well
return floor(floatval(str_replace(',', '.', str_replace('.', '', $val))));
}, $array);
// Calculate total amount
$total = array_sum($array);

You can make a blacklist array, and check wether the value is contained in that array. If not, add it up to a variable:
<?php
// The values you don't want.
$blacklist = array( "1:11", "12", "13", "14", "15", "16" );
$tr_arr = $this->data['troops_intrap_num']; // this is the above array from db
$explode_arr = explode(" ", $tr_arr); // exploding the array
$array_sum = 0;
foreach( $explode_arr as $index => $value )
{
if( !in_array($value, $blacklist) )
{
$value = str_replace(",",".", str_replace(".","",$value) );
$array_sum += floatval($value);
}
}
print "the sum of the array is: " . $array_sum;
?>

Not sure if I understand what you want exactly, but here's what I would do. It's a little more complicated to settle for a larger variety of array values so you can use it even if you change it a little.
I'd do a foreach loop of the array, ignore invalid values (the string and the zero), take the valid values, get the whole number preceding the comma and then add it to the sum.
Of course there are easier and shorter variants for this, but I'm not sure how much your code would vary.
$tr_arr = $this->data['troops_intrap_num']; // this is the above array from db
$explode_arr = explode(" ", $tr_arr); // exploding the array
$sum = 0;
foreach($explode_arr as $key => $value) {
if($key == 0 OR !is_numeric($value)) {
// omit the first string, OR alternately omit all not-numbers (not sure if you need to remove the first one specificaly)
continue;
}
if(!$value) {
// omit the zero at the end
continue;
}
$number = (int)substr($value, 0, strpos($value, ','));
$sum = $sum + $number;
}
echo $sum;
$sum will be what you are looking for, if I understood you correctly.

You want to tally all of the values that precede a comma while iterating. strstr() with a third parameter of true will extract the substring before the needle (and return false if there is no needle).
Code: (Demo)
$array = array(
'1:11',
'1,12',
'2,13',
'3,14',
'4,15',
'5,16',
'0',
);
$total = 0;
foreach ($array as $value) {
$total += (int)strstr($value, ',', true);
}
echo $total; // 15

Related

PHP array_unique is not returning unique values [duplicate]

My array is :
$array= array(4,3,4,3,1,2,1);
And I'd like to output it like below:
Output = 2
(As 2 is present only once)
This is what I've tried:
$array = array(4, 3, 4, 3, 1, 2, 1);
$array1 = array(4, 3, 4, 3, 1, 2, 1);
$array_diff = array_diff($array, $array1);
*Read last section of this an for the most stable technique the avoids fringe case issues -- it is also the most verbose.
One-liner with no loops: (Demo)
var_export(array_keys(array_intersect(array_count_values($array),[1])));
The breakdown:
array_keys( // return the remaining keys from array_count_values
array_intersect( // filter the first array by second
array_count_values($array), // count number of occurrences of each value
[1] // identify the number of occurrences to keep
)
)
if you (or any future reader) wants to keep more values, replace the second parameter/array in array_intersect().
for instance:
you want to keep 1,2,and 3: array(1,2,3) or [1,2,3]
p.s. For the record, you can use array_filter() with a custom function to omit all non-1 count values, but I have used array_intersect() because the syntax is more brief and IMO easier to read.
p.s. thought I'd revisit and include a PHP7.4 technique and compare against other function-based techniques...
Code: (Demo)
$numbers = [4, 3, 4, 3, 1, 2, 1];
var_export(
array_keys(
array_intersect(
array_count_values($numbers),
[1]
)
)
);
echo "\n---\n";
var_export(
array_keys(
array_filter(
array_count_values($numbers),
function($count) {
return $count === 1;
}
)
)
);
echo "\n---\n";
// PHP7.4+
var_export(
array_keys(
array_filter(
array_count_values($numbers),
fn($count) => $count === 1
)
)
);
*For similar tasks which have values which are not guaranteed to be integers, array_count_values() will complain with "Warning: array_count_values(): Can only count string and integer values".
Even a classic loop that uses values as first level keys like #LF00's answer will suffer potential side effects due to floats and numeric values being cast as integers automatically.
This means that a more general-use solution would be: (Demo)
$result = [];
foreach ($array as $index => $value) {
foreach ($array as $i => $v) {
if ($value === $v && $index !== $i) {
continue 2; // duplicate found, stop checking this value; do not retain
}
}
$result[] = $value;
}
var_export($result);
You could use the array_count_values() php function.
For example:
$numbers = [4, 3, 4, 3, 1, 2, 1];
// build count array as key = number and value = count
$counter_numbers = array_count_values($numbers);
print_r($counter_numbers);
Output :
Array
(
[4] => 2
[3] => 2
[1] => 2
[2] => 1
)
Then loop through the new array to get non-repeated values :
$unique_numbers = [];
foreach ($counter_numbers as $number => $count) {
if ($count === 1) {
$unique_numbers[] = $number;
}
}
print_r($unique_numbers);
Output :
Array
(
[0] => 2
)
You can do it like this: Count the occurrences of each element, then filter out the occurrences bigger than 1.
$array = [4, 3, 4, 3, 1, 2, 1];
foreach ($array as $v)
{
$arr[$v][] = 1; // doesn't matter if 1 is set to a different value
}
foreach($arr as $k => $v)
{
if (count($v) == 1) {
$o[] = $k;
}
}
print_r($o);
result:
Array
(
[0] => 2
)
If in your scenario there will be only one unique value you could use:
$array= array(4,3,4,3,1,2,1);
$singleValue = array_search(1, array_count_values($array));
var_dump($singleValue) // Outputs: 2

Php associative array sort and get key with highest length [duplicate]

This question already has answers here:
Read the longest string from an array in PHP 5.3
(3 answers)
Closed 2 years ago.
Hey i have an associative array which has keys as String and values as Int.
So from that associative array i need to get the key which has the highest value and if multiple keys have the same value then i need the key with the highest length.
So whats the most efficient way of doing this?
example
array = (
'abc' => 10,
'def' => 8,
'fff' => 3,
'abcr' => 10,
'adsfefs' => 10
)
So for this i should get output as adsfefs
You can use array_keys and pass a second parameter to filter the returned keys to only include the max ones. You can then find the longest key by using array_reduce and a function that checks the lengths of the strings and throws out the shortest one, like so:
$array = array(
'abc' => 10,
'def' => 8,
'fff' => 3,
'abcr' => 10,
'adsfefs' => 10
);
$keys = array_keys($array, max($array));
$longestKey = array_reduce($keys, function ($a, $b) { return strlen($a) > strlen($b) ? $a : $b; });
var_dump($longestKey);
Be aware that if there are two or more strings that are the same length, it will return the last one.
Use arsort($data); to perform the initial sort of the value data, then use array_values to identify the largest value. With the largest value find which keys have this value and then iterate through and find the longest key value.
$data = array('bob' => 3, 'rob' => 4, 'nigel' => 6,'john' => 6, 'tony' => 6 );
// Sort array in descending value order
arsort($data);
// Get the first value (will be the largest value)
$maxValue = array_values($data)[0];
// Get an array of all keys with this value
$keys = array_keys($data, $maxValue);
// Find longest key
$maxKey = '';
foreach ($keys as $key) {
if (strlen($key) > strlen($maxKey)) {
$maxKey = $key;
}
}
// Output
print "Largest Value = $maxValue\n";
print "Largest Key with value of $maxValue is $maxKey\n";
Use arsort(array) to reverse sort them by value
foreach resulting array as long as value is not changing. Store each key in other array in format
[key] => strlen(key);
So arsort(other_array) and take first element. It should be the one with longest keys (but be aware that if there was many keys that has the same length you should add some other conditions to choose between them).
<?php
$sid = array(
'abc' => 10,
'def' => 8,
'fff' => 3,
'abcr' => 10,
'adsfefs' => 10
);
arsort($sid);
$prev_val = null;
$keys = Array();
foreach ($sid as $k=>$v) {
if ($k < $prev_val) break;
$keys[$k] = strlen($k);
$prev_val = $k;
}
arsort($keys);
echo "Longest key with highest value is: " . array_keys($keys)[0] . "\n";
?>

Shuffle the order of keys in an associative array, if they have the same values?

Given an associative array like this, how can you shuffle the order of keys that have the same value?
array(a => 1,
b => 2, // make b or c ordered first, randomly
c => 2,
d => 4,
e => 5, // make e or f ordered first, randomly
f => 5);
The approach I tried was to turn it into a structure like this and shuffle the values (which are arrays of the original keys) and then flatten it back into the original form. Is there a simpler or cleaner approach? (I'm not worried about efficiency, this is for small data sets.)
array(1 => [a],
2 => [b, c], // shuffle these
4 => [d],
5 => [e, f]); // shuffle these
function array_sort_randomize_equal_values($array) {
$collect_by_value = array();
foreach ($array as $key => $value) {
if (! array_key_exists($value, $collect_by_value)) {
$collect_by_value[$value] = array();
}
// note the &, we want to modify the array, not get a copy
$subarray = &$collect_by_value[$value];
array_push($subarray, $key);
}
arsort($collect_by_value);
$reordered = array();
foreach ($collect_by_value as $value => $array_of_keys) {
// after randomizing keys with the same value, create a new array
shuffle($array_of_keys);
foreach ($array_of_keys as $key) {
array_push($reordered, $value);
}
}
return $reordered;
}
I rewrote the entire code, since I found another way which is a lot simpler and faster than the old one(If you are still interested in the old one see the revision):
old code (100,000 executions): Ø 4.4 sec.
new code (100,000 executions): Ø 1.3 sec.
Explanation
First we get all unique values from the array with array_flip(), since then the values are the keys and you can't have duplicate keys in an array we have our unique values. We also create an array $result for then storing our result in it and $keyPool for storing all keys for each value.
Now we loop through our unique values and get all keys which have the same value into an array with array_keys() and save it in $keyPool with the value as key. We can also right away shuffle() the keys array, so that they are already random:
foreach($uniqueValues as $value => $notNeeded){
$keyPool[$value] = array_keys($arr, $value, TRUE);
shuffle($keyPool[$value]);
}
Now we can already loop through our original array and get a key with array_shift() from the $keyPool for each value and save it in $result:
foreach($arr as $value)
$result[array_shift($keyPool[$value])] = $value;
Since we already shuffled the array the keys already have a random order and we just use array_shift(), so that we can't use the key twice.
Code
<?php
$arr = ["a" => 1, "b" => 1, "c" => 1, "d" => 1, "e" => 1, "f" => 2,
"g" => 1, "h" => 3, "i" => 4, "j" => 5, "k" => 5];
function randomize_duplicate_array_value_keys(array $arr){
$uniqueValues = array_flip($arr);
$result = [];
$keyPool = [];
foreach($uniqueValues as $value => $notNeeded){
$keyPool[$value] = array_keys($arr, $value, TRUE);
shuffle($keyPool[$value]);
}
foreach($arr as $value)
$result[array_shift($keyPool[$value])] = $value;
return $result;
}
$result = randomize_duplicate_array_value_keys($arr);
print_r($result);
?>
(possible) output:
Array (
[b] => 1
[g] => 1
[a] => 1
[e] => 1
[d] => 1
[f] => 2
[c] => 1
[h] => 3
[i] => 4
[k] => 5
[j] => 5
)
Footnotes
I used array_flip() instead of array_unique() to get the unique values from the array, since it's slightly faster.
I also removed the if statement to check if the array has more than one elements and needs to be shuffled, since with and without the if statement the code runs pretty much with the same execution time. I just removed it to make it easier to understand and the code more readable:
if(count($keyPool[$value]) > 1)
shuffle($keyPool[$value]);
You can also make some optimization changes if you want:
Preemptively return, if you get an empty array, e.g.
function randomize_duplicate_array_value_keys(array $arr){
if(empty($arr))
return [];
$uniqueValues = array_flip($arr);
$result = [];
//***
}
Preemptively return the array, if it doesn't have duplicate values:
function randomize_duplicate_array_value_keys(array $arr){
if(empty($arr))
return [];
elseif(empty(array_filter(array_count_values($arr), function($v){return $v > 1;})))
return [];
$uniqueValues = array_flip($arr);
$result = [];
//***
}
Here's another way that iterates through the sorted array while keeping track of the previous value. If the previous value is different than the current one, then the previous value is added to a new array while the current value becomes the previous value. If the current value is the same as the previous value, then depending on the outcome of rand(0,1) either the previous value is added to the new list as before, or the current value is added to the new list first:
<?php
$l = ['a' => 1,'b' => 2, 'c' => 2,
'd' => 4,'e' => 5,'f' => 5];
asort($l);
$prevK = key($l);
$prevV = array_shift($l); //initialize prev to 1st element
$shuffled = [];
foreach($l as $k => $v) {
if($v != $prevV || rand(0,1)) {
$shuffled[$prevK] = $prevV;
$prevK = $k;
$prevV = $v;
}
else {
$shuffled[$k] = $v;
}
}
$shuffled[$prevK] = $prevV;
print_r($shuffled);

Grab a part on array (inside array) PHP

I need to grab data within array (inside array) that will grab only the second and the third rows of each line.
<?php
$salaries = array(
//I WANT TO MAKE A NEW ARRAY FROM ALL THE SECOND AND THE THIRD ROWS
"a" => 2000, 1500, 3000, 1950
"b" => 1000, 2300, 2233, 2400
"c" => 500 , 6590, 1024, 2048
//FOR EXAMPLE RESULTS IN THIS CASE WOULD BE :
//$newarray = array(1500,3000,2300,2233,6590,2048);
);
?>
If there is no direct command for that loops would be fine :)
Thanks !
First of all, your array declaration isn't syntactically valid.
If you meant it to be a multi-dimensionl array as follows:
$salaries = array(
"a" => array(2000, 1500, 3000, 1950),
"b" => array(1000, 2300, 2233, 2400),
"c" => array(500 , 6590, 1024, 2048)
);
Then, this can be done using two loops. In the first loop, loop through all the sub-arrays. Loop through the values in each sub-array, check if the value is second or third. If so, add it to the new array:
foreach ($salaries as $key => $arr) {
for ($i=0; $i < count($arr); $i++) {
if ($i == 1 || $i == 2) {
$result[$key][] = $arr[$i];
}
}
}
print_r($result);
Demo
For completeness, I'm going to add the solution for the case when the values are comma-separated strings, not arrays:
$salaries = array(
"a" => '2000, 1500, 3000, 1950',
"b" => '1000, 2300, 2233, 2400',
"c" => '500 , 6590, 1024, 2048'
);
The logic is exactly the same, but instead of accessing the inner array elements directly, you'll have to use explode() to create an array of the values. Then use array_slice() to get the second and third elements, and create a new array from it:
$result = array();
foreach ($salaries as $key => $value) {
$pieces = explode(', ', $value);
$slice[$key] = array_slice($pieces, 1, 2);
$result = array_merge($result, $slice);
}
Demo

PHP Max for multiple values to be displayed

This is what i currently have:
$sum = array_count_values($_POST);
$max_value = max($sum);
$max_key = array_search($max_value, $sum);
$sum containes for example A->2 B->6 C->4
and max($sum) will then take 6, $max_key will get the key of that 6 (B in this case).
Now what if $sum is like this? A->3 B->7 C->7, that it takes B->6 as the highest value.
I want $max_key to be an array containing both the letters B and C in this case
so i can use it in a foreach loop.
Thanks, Laurent
If you just want keys of max values from array try this,
$array = array("A" => 2,"B" => 7,"C" => "7");
$maxs_keys = array_keys($array, max($array));
print_r($maxs_keys);
Codepad Demo.
If you have PHP 5.3, then you can use conveniently array_filter like this:
$sum = array( 'A'=>3, 'B'=>7, 'C'=>7 );
$max_value = max($sum);
$result = array_filter( $sum, function($x) use ($max_value) { return $x === $max_value; } );
print_r($result);
The snippet above will print what you want:
Array
(
[B] => 7
[C] => 7
)
If you want just the keys of the result, use array_keys to extract them.

Categories