Trouble finding odd results of an array - php

I can't seem to find the answer to these problem. I have the following php code.
$r = 1,2,3,4,5,6 and so on
and i want to get the number like this
$result = 1,3,5
or if i have
$s = b,c,d,e,f,g,h,i...and so on
the result should be
$results c,e,g,i

Pretty easy with numbers, the trick with letters is to use ord()
$arr = array(1,2,3,4,5,6);
$arr = array_filter ($arr, function ($number) {
return $number % 2;
});
print_r($arr);
$arr = array('a', 'b', 'c', 'd', 'e');
$arr = array_filter ($arr, function ($letter) {
return ord($letter) % 2;
});
print_r($arr);
Output :
Array (
[0] => 1
[2] => 3
[4] => 5
)
Array (
[0] => a
[2] => c
[4] => e
)
And here is a generic solution, working with both letters and numbers :
$arr = array_filter ($arr, function ($value) {
$value = is_int($value) ? $value : ord($value);
return $value % 2;
});

This will work:
$a = array(1,2,3,4,5,6);
foreach($a as $k => $v){
if($k&1){
unset($a[$k]);
}
}
print_r($a);

Related

Map array with initial letter in PHP

I wish to group a word list in an array with the initial letter.
function alpha($str) {
$result[substr($str,0,1)] = $str;
return $result;
}
$a = ['abc','cde','frtg','acf'];
$b = array_map('alpha', $a);
print_r($b);
What I need:
Array
(
[a] => abc,acf
[c] => cde
[f] => frtg
)
What I get:
Array
(
[0] => Array
(
[a] => abc
)
[1] => Array
(
[c] => cde
)
[2] => Array
(
[f] => frtg
)
[3] => Array
(
[a] => acf
)
)
How about that :
$answer = [];
$a = ['abc','cde','frtg','acf'];
foreach($a as $word){
$key = substr($word,0,1);
if (isset($answer[$key])){
$answer[$key] .= "," . $word;
} else {
$answer[$key] = $word;
}
}
Just add a variable $c and loop over arrays of array using two foreach and group by alphabet...
function alpha($str) {
$result[substr($str,0,1)] = $str;
return $result;
}
$a = ['abc','cde','frtg','acf'];
$b = array_map('alpha', $a);
#print_r($b);
$c = [];
foreach ($b as $key => $values) {
foreach ($values as $key => $value) {
if(!isset($c[$key])){
$c[$key]=$value;
}else{
$c[$key].= "," . $value;
}
}
}
echo "<PRE>";
print_r($c);
Outupt:
Array
(
[a] => abc,acf
[c] => cde
[f] => frtg
)
The function array_map maps to the original indexes but you want new indexes and an altered array, if there are more values with the same initial character. Therefore array_map don't work for you. You could create your new array this way:
$a = ['abc','cde','frtg','acf'];
$b = Array();
$c = Array();
foreach( $a as $v )
{
// multidimensional array
$b[substr($v,0,1)][] = $v;
// comma separated string
$c[substr($v,0,1)] = (isset($c[substr($v,0,1)])) ?
$c[substr($v,0,1)].",$v" : $v;
}
If the first character can also be multibyte Unicode such as ° or €, mb_substr() must be used! Solution with foreach:
$result = [];
$a = ['abc','€de','frtg','acf'];
foreach($a as $word){
$key = mb_substr($word,0,1);
$result[$key] = array_key_exists($key,$result)
? ($result[$key].",".$word)
: $word
;
}
Solution with array_reduce():
$result = array_reduce($a,function($carry,$item){
$key = mb_substr($item,0,1);
$carry[$key] = array_key_exists($key,$carry) ? ($carry[$key].",".$item) : $item;
return $carry;
},[]);
var_export($result);
Output:
array (
'a' => 'abc,acf',
'€' => '€de',
'f' => 'frtg',
)
I think your intention is to store each word into arrays according to its first letter. In this case, the multidimensional array is the right choice.
$array = ['abc','cde','frtg','acf'];
$new_array = array();
foreach($array as $v){
$letter = substr($v,0,1);
if(!isset($new_array[$letter])) {$new_array[$letter] = array();}
array_push($new_array[$letter], $v);
}
print_r($new_array);

Create nested array by array of keys

I've some difficulties creating a nested array by array of keys and assigning a value for the last nested item.
For example, lets $value = 4; and $keys = ['a', 'b', 'c'];
The final result should be:
[
'a' => [
'b' => [
'c' => 4
]
]
]
I've tried with a recursion, but without success.
Any help would be greatly appreciated.
you don't need recursion, just do it from the right to left:
$a = $value;
for ($i = count($keys)-1; $i>=0; $i--) {
$a = array($keys[$i] => $a);
}
or the even shorter version from #felipsmartins:
$a = $value;
foreach (array_reverse($keys) as $valueAsKey) $a = [$valueAsKey => $a];
Your can try it.
$value = 4;
$keys = ['a', 'b', 'c'];
$a = $value;
$i=count($keys)-1;
foreach($keys as $key){
$a = array($keys[$i] => $a);
$i--;
}
print_r($a);
Output
Array
(
[a] => Array
(
[b] => Array
(
[c] => 4
)
)
)
Solution by getting a nested item in the resulting array by reference:
$value = 4;
$keys = ['a', 'b', 'c'];
$result = [];
$reference = &$result;
foreach($keys as $key) {
if (!array_key_exists($key, $reference)) $reference[$key] = [];
$reference = &$reference[$key];
}
$reference = $value;
print_r($result);

How to merge two arrays by summing the merged values [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
PHP: How to sum values of the array of the same key
I am looking for an array_merge() function that does NOT replace values, but ADDS them.
Example, this is the code I am trying:
echo "<pre>";
$a1 = array(
"a" => 2
,"b" => 0
,"c" => 5
);
$a2 = array(
"a" => 3
,"b" => 9
,"c" => 7
,"d" => 10
);
$a3 = array_merge($a1, $a2);
print_r($a3);
Sadly, this outputs this:
Array
(
[a] => 3
[b] => 9
[c] => 7
[d] => 10
)
I then tried, instead of array_merge, just simply adding the two arrays
$a3 = $a1 + $a2;
But this outputs
Array
(
[a] => 2
[b] => 0
[c] => 5
[d] => 10
)
What I truly want is to be able to pass as many arrays as needed, and then get their sum. So in my example, I want the output to be:
Array
(
[a] => 5
[b] => 9
[c] => 12
[d] => 10
)
Of course I can schlepp and build some function with many foreach etc, but am looking or a smarter, cleaner solution. Thanks for any pointers!
$sums = array();
foreach (array_keys($a1 + $a2) as $key) {
$sums[$key] = (isset($a1[$key]) ? $a1[$key] : 0) + (isset($a2[$key]) ? $a2[$key] : 0);
}
You could shorten this to the following using the error suppression operator, but it should be considered ugly:
$sums = array();
foreach (array_keys($a1 + $a2) as $key) {
$sums[$key] = #($a1[$key] + $a2[$key]);
}
Alternatively, some mapping:
$keys = array_fill_keys(array_keys($a1 + $a2), 0);
$sums = array_map(function ($a1, $a2) { return $a1 + $a2; }, array_merge($keys, $a1), array_merge($keys, $a2));
Or sort of a combination of both solutions:
$sums = array_fill_keys(array_keys($a1 + $a2), 0);
array_walk($sums, function (&$value, $key, $arrs) { $value = #($arrs[0][$key] + $arrs[1][$key]); }, array($a1, $a2));
I think these are concise enough to adapt one of them on the spot whenever needed, but to put it in terms of a function that accepts an unlimited number of arrays and sums them:
function array_sum_identical_keys() {
$arrays = func_get_args();
$keys = array_keys(array_reduce($arrays, function ($keys, $arr) { return $keys + $arr; }, array()));
$sums = array();
foreach ($keys as $key) {
$sums[$key] = array_reduce($arrays, function ($sum, $arr) use ($key) { return $sum + #$arr[$key]; });
}
return $sums;
}
My contribution:
function array_merge_numeric_values()
{
$arrays = func_get_args();
$merged = array();
foreach ($arrays as $array)
{
foreach ($array as $key => $value)
{
if ( ! is_numeric($value))
{
continue;
}
if ( ! isset($merged[$key]))
{
$merged[$key] = $value;
}
else
{
$merged[$key] += $value;
}
}
}
return $merged;
}
Pass as many arrays to it as you want. Feel free to add some more defense, ability to accept multidimensional arrays, or type checking.
Demo: http://codepad.org/JG6zwAap
its not so complicate
do something like:
$a3 = $a1;
foreach($a2 as $k => $v) {
if(array_key_exists($k, $a3)) {
$a3[$k] += $v;
} else {
$a3[$k] = $v;
}
}

PHP: Count-IF for Arrays

What would be the most efficient way of counting the number of times a value appears inside an array?
Example Array ('apple','apple','banana','banana','kiwi')
Ultimately I want a function to spit out the percentages for charting purposes
(e.g. apple = 40%, banana = 40%, kiwi = 20%)
Just put it through array_count_values. The percentages should be easy...
$countedArray = array_count_values($array);
$total = count($countedArray);
foreach ($countedArray as &$number) {
$number = ($number * 100 / $total) . '%';
}
Use array_count_values():
<?php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
?>
The above example will output:
Array
(
[1] => 2
[hello] => 2
[world] => 1
)
$a = Array ('apple','apple','banana','banana','kiwi');
$b = array_count_values($a);
function get_percentage($b,$a){
$a_count = count($a);
foreach ($b as $k => $v){
$ret[$k] = $v/$a_count*100."%";
}
return $ret;
}
$c = get_percentage($b,$a);
print_r($c);

Filter array - odd even

How can a filter out the array entries with an odd or even index number?
Array
(
[0] => string1
[1] => string2
[2] => string3
[3] => string4
)
Like, i want it remove the [0] and [2] entries from the array.
Or say i have 0,1,2,3,4,5,6,7,8,9 - i would need to remove 0,2,4,6,8.
foreach($arr as $key => $value) if($key&1) unset($arr[$key]);
The above removes odd number positions from the array, to remove even number positions, use the following:
Instead if($key&1) you can use if(!($key&1))
Here's a "hax" solution:
Use array_filter in combination with an "isodd" function.
array_filter seems only to work on values, so you can first array_flip and then use array_filter.
array_flip(array_filter(array_flip($data), create_function('$a','return $a%2;')))
You could also use SPL FilterIterator like this:
class IndexFilter extends FilterIterator {
public function __construct (array $data) {
parent::__construct(new ArrayIterator($data));
}
public function accept () {
# return even keys only
return !($this->key() % 2);
}
}
$arr = array('string1', 'string2', 'string3', 'string4');
$filtered = array();
foreach (new IndexFilter($arr) as $key => $value) {
$filtered[$key] = $value;
}
print_r($filtered);
<?php
function odd($var)
{
// returns whether the input integer is odd
return($var & 1);
}
function even($var)
{
// returns whether the input integer is even
return(!($var & 1));
}
$array1 = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);
$array2 = array(6, 7, 8, 9, 10, 11, 12);
echo "Odd :\n";
print_r(array_filter($array1, "odd"));
echo "Even:\n";
print_r(array_filter($array2, "even"));
?>
Odd :
Array
(
[a] => 1
[c] => 3
[e] => 5
)
Even:
Array
(
[0] => 6
[2] => 8
[4] => 10
[6] => 12
)
I'd do it like this...
for($i = 0; $i < count($array); $i++)
{
if($i % 2) // OR if(!($i % 2))
{
unset($array[$i]);
}
}
<?php
$array = array(0, 3, 5, 7, 20, 10, 99,21, 14, 23, 46);
for ($i = 0; $i < count($array); $i++)
{
if ($array[$i]%2 !=0)
echo $array[$i]."<br>";
}
?>
$array = array(0 => 'string1', 1 => 'string2', 2 => 'string3', 3 => 'string4');
// Removes elements of even-numbered keys
$test1 = array_filter($array, function($key) {
return ($key & 1);
}, ARRAY_FILTER_USE_KEY);
// Removes elements of odd-numbered-keys
$test2 = array_filter($array, function($key) {
return !($key & 1);
}, ARRAY_FILTER_USE_KEY);
This answer is a bit of an improvement over this answer. You can use anonymous functions instead of create_function. Also, array_filter takes an optional flag parameter that lets you specify that the callback function takes the key as its only argument. So you don't need to use array_flip to get an array of keys.

Categories