This question already has answers here:
How can I check if an array contains a specific value in php? [duplicate]
(8 answers)
Closed 7 years ago.
i have a foreach where i want to compare some strings from two arrays
output of variable $count_land
Array
(
["US"] => 186
["DE"] => 44
["BR"] => 15
["FR"] => 3
["other"] => 7
)
Other array:
$all_lands_array = ["CN", "DE", "US", "EU", "RU", "BR", "GB", "NL", "LU", "other", "IT"];
what i need is every key in the $all_lands_array that have the same letters from the $count_land array and save them in another variable
that means i need to get US, DE, BR, FR, other and save them in a new variable
i hope you understand what i need :)
this is my loop but it doesnt find any match.. but why?
foreach($all_lands_array as $lands){
if($lands == $count_land)
return "match";
else
return "no match!";
}
Because you just loop through one array and then check the value against the whole other array.
Checking for country codes:
$count_land = array
(
"US" => 186,
"DE" => 44,
"BR" => 15,
"FR" => 3,
"other" => 7
);
$all_lands_array = array("CN", "DE", "US", "EU", "RU", "BR", "GB", "NL", "LU", "other", "IT");
$matches = array();
foreach($count_land as $key => $val){
if(in_array($key, $all_lands_array)){
$matches[$key] = $val; // add matches to array;
}else{
// do nothing
}
}
print_r($matches);die;
returns:
Array ( [US] => 186 [DE] => 44 [BR] => 15 [other] => 7 )
You have to save the countries in a variable as an array and use in_array to check if an element is in that array:
$found = array();
$countries = array_keys($count_land); //stores: US,DE..etc
foreach($all_lands_array as $country){
if(in_array($country, $countries)){ //if a country name is found in $countries array,
//OPTIONALLY: exclude 'other'
//if(in_array($country, $countries) && $country !='other')
$found[] = $country; //store them in the $found variable
}
}
Test
$count_land = array('US'=>1,'DE'=>1,'BR'=>1,'FR'=>1,'other'=>1);
$all_lands_array = ["CN", "DE", "US", "EU", "RU", "BR", "GB", "NL", "LU", "other", "IT"];
var_dump($found);
array(4) {
[0]=>
string(2) "DE"
[1]=>
string(2) "US"
[2]=>
string(2) "BR"
[3]=>
string(5) "other"
}
Related
I need to group values in my flat array so that each non-integer value starts a new group/row in my result array and every integer value encountered until the next occurring non-integer should be pushed into a subarray in the respective group/row.
Input:
$unitsList = [
"Aulas Gratuitas",
"149",
"151",
"153",
"Módulo 0",
"964",
"989",
"Módulo 1",
"985",
"1079",
"1001",
"1003"
"Módulo 2",
"1009"
];
Current code:
$newArr = array();
foreach( $unitsList as $item ) {
if( !is_numeric($item) ) {
$title = array( "title" => $item, "units" => "" );
array_push( $newArr, $title);
} elseif ( is_numeric($item) ) {
$number = $item;
array_push( $newArr, $number);
}
}
Current result:
[
[
"title" => "Aulas Gratuitas",
"units" => ""
]
"149",
"151",
"153",
[
"title" => "Módulo 0",
"units" => ""
],
"964",
"989",
[
"title" => 'Módulo 1',
"units" => ""
],
"985",
"1079",
"1001",
"1003"
[
"title" => 'Módulo 2',
"units" => ''
],
"1009"
]
As you can see, I am having a hard time adding the numbers into the "units" key.
Desired result:
[
[
"title" => "Aulas Gratuitas",
"units" => ["149", "151", "153"]
],
[
"title" => 'Módulo 0',
"units" => ["964", "989"]
],
[
"title" => 'Módulo 1',
"units" => ["985", "1079", "1001", "1003"]
],
[
"title" => "Módulo 2",
"units" => ["1009"]
]
]
So that you don't need to keep track of first level indexes, use a reference variable and push related data into that AFTER pushing the new row into the result array.
Code: (Demo)
$result = [];
foreach ($array as $value) {
if (!ctype_digit($value)) {
unset($units);
$units = [];
$result[] = ['title' => $value, 'units' => &$units];
} else {
$units[] = $value;
}
}
var_export($result);
unset() is used to destroy the reference to the previous group, otherwise newly pushed data would be sent to two (or more) places in the result array.
Reference variables have a default value of null. If your title values are guaranteed to be followed by an integer/unit value, then $units = []; can be removed. If you have a title and then another title there will be no data for the former title group. With the explicit array declaration, the group will have an empty units array instead of null.
Related questions answered with the same general technique:
Group array of objects into deeper parent-child structure
Split flat array into grouped subarrays containing values from consecutive key in the input array
How to split a string by repeated characters in PHP?
If you are running PHP7.3 or higher (and by this point you definitely should be) AND you are intimidated/mystified by using a reference variable, then you can leverage array_key_last() to locate the latest created array row.
Code: (Demo)
$result = [];
foreach ($array as $value) {
if (!ctype_digit($value)) {
$result[] = ['title' => $value, 'units' => []];
} else {
$result[array_key_last($result)]['units'][] = $value;
}
}
var_export($result);
Items in the given list aren't regular. The first item has three units, and the second has two units. We cannot convert them into the expected structure without controlling the type of each item. My solution is below. I added explanations as a comment line.
$values = array(
"string",
11111,
22222,
33333,
"string_2",
44444,
55555
);
$formattedArray = [];
$index = -1;
foreach ($values as $value) {
// If the value is a string, create the new array structure item and assign the title
if (is_string($value)) {
$index++;
$formattedArray[$index]['title'] = $value;
$formattedArray[$index]['units'] = [];
// The rest of the code in "foreach scope" is for integer values, so skip the remaining part
continue;
}
// If the following line is executing, the value is an integer
// Push the value to the current item's units
$formattedArray[$index]['units'][] = $value;
}
var_dump($formattedArray);
$originalArray = ['a', 1, 2, 3, 'b', 4, 5, 6];
function formatArray($input) {
$output = [];
foreach($input as $inputRow) {
if (is_string($inputRow)) {
$output[] = ['title' => $inputRow, 'units' => []];
} elseif (count($output)) {
$output[count($output)-1]['units'][] = $inputRow;
}
}
return $output;
}
var_dump(formatArray($originalArray));
Note that your numbers after the title CANNOT be strings, otherwise this function will recognize it as new titles.
This code will output:
array(2) {
[0]=>
array(2) {
["title"]=>
string(1) "a"
["units"]=>
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
}
[1]=>
array(2) {
["title"]=>
string(1) "b"
["units"]=>
array(3) {
[0]=>
int(4)
[1]=>
int(5)
[2]=>
int(6)
}
}
}
Approach: loop over values in array, check for value if its converted to int is equal to 0, So group by that key, otherwise accumelate they next elements.
<?php
$unitsList = [ "Aulas Gratuitas", "149", "151", "153", "Módulo 0", "964", "989", "Módulo 1", "985", "1079", "1001", "1003", "Módulo 2", "1009" ];
$result = [];
foreach ($unitsList as $key => $value) {
if(intval($value)==0){
$result[] = ['title' => $value, 'units' => []];
}else{
$result[count($result)-1]['units'][] = $value;
}
}
print_r(array_values($result));
?>
I have a list of colors in $colors and want to remove certain colors if another color is present in the loop.
For example: If the color blue is part of the loop, I want to remove the color dark-blue from the list.
I tried to check if the color blue is in the array. But I'm not sure how and how I can ignore it after that in the foreach loop.
This is my current code:
<?php
$colors = $product->get_attribute('colors');
if( strpos($colors, 'blue') !== false ) :
$has_blue = true;
else :
$has_blue = false;
endif;
foreach ( $colors as $color ) :
// content
endforeach;
?>
I think my approach isn't the best practice method because I need to add a if/else statement for every color.
Is there a better way to do this?
Here's the array of $colors (one item):
array(6) {
[0]=>
object(WP_Term)#27294 (10) {
["term_id"]=>
int(85)
["name"]=>
string(5) "Blue"
["slug"]=>
string(5) "blue"
["term_group"]=>
int(0)
["term_taxonomy_id"]=>
int(85)
["taxonomy"]=>
string(7) "color"
["description"]=>
string(0) ""
["parent"]=>
int(0)
["count"]=>
int(720)
["filter"]=>
string(3) "raw"
}
You are checking it the wrong way. There are still some things missing in your question. First of all what is the data type of this?
$colors = $product->get_attribute('colors');
Is it an array? Or some data loop? Data loops are pretty much same as array. Is it a multidimensional array? If not then use in_array() function to check for the color.
In this way you can deduct the use of foreach. If it is a multidimensional array then you have put the if conditionals inside foreach loop like this:
foreach ( $colors as $color ) :
if( strpos($color, 'blue') !== false ) :
$has_blue = true;
else :
$has_blue = false;
endif;
endforeach;
If you need anything else please elaborate your question some more.
You can create a FilterIterator. And because name in your example is capitailized I use stripos instead of strpos.
class ColorFilter extends FilterIterator
{
private $_filter;
public function __construct($colors, $filter)
{
parent::__construct(new ArrayIterator($colors));
$this->_filter = $filter;
}
public function accept()
{
$color = $this->getInnerIterator()->current();
return stripos($color->name, $this->_filter) === false;
}
}
foreach(new ColorFilter($colors, 'blue') as $filted_color)
{
}
I think you can filter the colors dynamically like this:
$colors_3 = [
0 => (object) [
"name" => "Blue",
],
1 => (object) [
"name" => "Dark Blue",
],
2 => (object) [
"name" => "Red",
],
3 => (object) [
"name" => "Dark Red",
],
4 => (object) [
"name" => "Dark Orange",
],
5 => (object) [
"name" => "Purple",
],
];
function filter_colors($colors)
{
$filter_me = [];
$filtered_colors = [];
foreach ($colors as $color) {
$parts = explode(" ", $color->name);
if (count($parts) == 1) {
$filter_me[] = $color->name;
}
}
foreach ($colors as $color) {
$parts = explode(" ", $color->name);
foreach ($parts as $part) {
if (in_array($part, $filter_me)) {
if (count($parts) == 1) {
break;
}
continue 2;
}
}
$filtered_colors[] = $color;
}
return $filtered_colors;
}
print_r(filter_colors($colors_3);
We get a filtered array:
Array
(
[0] => stdClass Object
(
[name] => Blue
)
[1] => stdClass Object
(
[name] => Red
)
[2] => stdClass Object
(
[name] => Dark Orange
)
[3] => stdClass Object
(
[name] => Purple
)
)
If this doesn't work for some reason with the real data please update your question to include more test data.
I want to compare the values of sandra_array with john_array and then with sem_array.
I can compare sandra_array with john_array with:
<?php
$sandra_array = array("soccer" => "10", "basketball" => "20", "atletics" => "40");
$john_array = array("soccer" => "15", "basketball" => "15", "atletics" => "45");
$sem_array = array("soccer" => "5", "basketball" => "10", "atletics" => "50");
$common_sports = array_keys(array_intersect_key($sandra_array, $john_array));
$points_sandra_array = $points_john_array = array_fill_keys($common_sports, 0);
foreach ($common_sports as $common_sport) {
if ($sandra_array[$common_sport] > $john_array[$common_sport]) {
$points_sandra_array[$common_sport]++;
} else if ($sandra_array[$common_sport] < $john_array[$common_sport]) {
$points_john_array[$common_sport]++;
}
}
foreach ($common_sports as $common_sport) {
}
echo "Sandra (", array_sum($points_sandra_array).") vs John (", array_sum($points_john_array).")";
?>
Result
Sandra (1) vs John (2)
I want to have also the results of Sandra against Sem. Like this:
Sandra (1) vs John (2)
Sandra (2) vs Sem(1)
I was thinking about making the following multidimensional array:
$array_other_players = array($john_array,$sem_array);
and then with foreach I will compare first the points of Sandra with the points of John and then with the points of Sem. But I don't know how to do it.
Could you help me with this?
The solution is:
First declare an array containing opponents players' array, like this:
$players_array = array('John' => $john_array, 'Sem' => $sem_array);
And then loop through each opponent player to calculate the final score.
So your code should be like this:
$sandra_array = array("soccer" => "10", "basketball" => "20", "atletics" => "40");
$john_array = array("soccer" => "15", "basketball" => "15", "atletics" => "45");
$sem_array = array("soccer" => "5", "basketball" => "10", "atletics" => "50");
// Declare an array containing opponents players' array
$players_array = array('John' => $john_array, 'Sem' => $sem_array);
// Loop through each opponent player to calculate the final score
foreach($players_array as $opponent_player => $opponent_player_array){
$common_sports = array_keys(array_intersect_key($sandra_array, $opponent_player_array));
$points_sandra_array = $points_opponent_array = array_fill_keys($common_sports, 0);
foreach ($common_sports as $common_sport) {
if ($sandra_array[$common_sport] > $opponent_player_array[$common_sport]) {
$points_sandra_array[$common_sport]++;
} else if ($sandra_array[$common_sport] < $opponent_player_array[$common_sport]) {
$points_opponent_array[$common_sport]++;
}
}
echo "Sandra (". array_sum($points_sandra_array).") vs {$opponent_player} (". array_sum($points_opponent_array) .")<br />";
}
Output:
Sandra (1) vs John (2)
Sandra (2) vs Sem (1)
I have an array like this:
$pricing = array(
"2" => 8.23,
"5" => 10.97,
"10" => 13.28,
"15" => 15.40,
"20" => 18.15,
"25" => 20.36,
"30" => 22.84,
"40" => 25.60,
"50" => 28.35,
"60" => 31.89,
"70" => 36.23,
"80" => 39.40,
"90" => 42.52,
"100" => 44.75
);
And I have a variable that has the client given value from 1 to 100.
Question is: what is the best and fastest way to find the next biggest key, if the key itself doesn't exist?
E.g. I have a variable with value of 12, and I need to get the price for that. According to the array here, the price would be 15.40 because the next biggest key is 15.
I could try and find key number '12', and if it doesn't exist, i would add one(12+1) and try again, until next key is found, but is there any function that could do this for me, or something even better/faster?
Edit: Clarification about the structure of the array.
Array is like it is in the example here. Keys are ordered as can be seen.
A simple foreach will do, but to guard against either empty arrays or a needle that's higher than the highest key, here's an implementation that will cover that as well:
function find(array $pricing, $needle)
{
$last = null; // return value if $pricing array is empty
foreach ($pricing as $key => $value) {
if ($key >= $needle) {
return $key; // found it, return quickly
}
$last = $key; // keep the last key thus far
}
return $last;
}
$result = find($pricing, 12); // 15
$result = find($pricing, 101); // 100
$result = find([], 12); // null
Assuming you are looking for the 'requiredKey' and that the array is sorted by key
This seem to do what you want.
Code:
<?php
$pricing = array(
"2" => 8.23,
"5" => 10.97,
"10" => 13.28,
"15" => 15.40,
"20" => 18.15,
"25" => 20.36,
"30" => 22.84,
"40" => 25.60,
"50" => 28.35,
"60" => 31.89,
"70" => 36.23,
"80" => 39.40,
"90" => 42.52,
"100" => 44.75
);
// What key we want...
$requiredKey = 12;
// outout in here
$foundKey = -1;
$foundValue = -1;
// always run the loop once...
do {
$foundKey = key($pricing); // store the current details
$foundValue = current($pricing);
next($pricing); // will be equal or greater
}
while ( current($pricing) !== false
&& $foundKey < $requiredKey);
echo '<pre>';
echo '<br />', 'key: ', $foundKey, ' value: ', $foundValue;
echo '</pre>';
Output:
key: 15 value: 15.4
Your logic is ok, you can do it using next()
http://php.net/manual/en/function.next.php
$search = 12;
$pricing = array(
"2" => 8.23,
"5" => 10.97,
"10" => 13.28,
"15" => 15.40,
"20" => 18.15,
"25" => 20.36,
"30" => 22.84,
"40" => 25.60,
"50" => 28.35,
"60" => 31.89,
"70" => 36.23,
"80" => 39.40,
"90" => 42.52,
"100" => 44.75
);
$result = null;
if (!isset($pricing[$search])) {
do {
} while (next($pricing) && $search > key($pricing));
$result = current($pricing);
} else {
$result = $pricing[$search];
}
echo $result;
Your lookup array will not change so it makes perfect sense to declare it as a constant (instead of a variable) and to make your code immediately understandable, give the constant a self-explanatory name.
const THRESHOLD_PRICES = [
2 => 8.23,
5 => 10.97,
10 => 13.28,
15 => 15.40,
20 => 18.15,
25 => 20.36,
30 => 22.84,
40 => 25.60,
50 => 28.35,
60 => 31.89,
70 => 36.23,
80 => 39.40,
90 => 42.52,
100 => 44.75
];
A valuable benefit of using a constant is that it is not necessary to explicitly pass the data into a function's scope.
In your function, I recommend type hinting the parameter and the return value -- again to make the code easier to understand.
Before iterating the array, do a quick scan of the keys for an exact match. Because of the way that php treats arrays as hashmaps, this is a very low-cost technique.
Next iterate the array and break the loop as soon as the array key is larger than the search value.
Regardless of if/when the loop breaks, the final iteration will declare the targeted price, so unconditionally return that float value.
function getThresholdPrice(int $search): float {
if (isset(THRESHOLD_PRICES[$search])) {
return THRESHOLD_PRICES[$search];
}
foreach (THRESHOLD_PRICES as $threshold => $price) {
if ($threshold > $search) {
break;
}
}
return $price;
}
Tests: (Demo)
foreach (range(1, 105, 13) as $test) {
printf("%d => %.02f\n", $test, getThresholdPrice($test));
}
Output:
1 => 8.23
14 => 15.40
27 => 22.84
40 => 25.60
53 => 31.89
66 => 36.23
79 => 39.40
92 => 44.75
105 => 44.75
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Search and replace inside an associative array
I think this may have been asked before. But I just want a simple solution.
I have an array like this:
Array ( "name" => "Krish",
"age" => "27",
"COD" => ""
)
I want to replace "" with "0"
Its a multidimentional array. The return value should be array too.
Edit: I tried preg_replace and str_replace. For some reason, these did not work for me.
$array = array(
"name" => "Krish",
"age" => "27",
"COD" => ""
);
you may loop the array and repalce what you want
foreach($array as $key => $value)
{
if($value == "") $array[$key] = 0;
}
Note:
if you know what key is it you can do it like this
$array['cod'] = 0;
$entry = array("name" => "Krish",
"age" => "27",
"COD" => "");
$arr = array_filter($entry, 'valcheck');
print_r($entry); //ORIGINAL ARRAY
print_r($arr); //MODIFIED ARRAY
function valcheck($var)
{
if($var === "")
return 0;
else
return $var;
}
if your array is $array:
$array['COD'] = "0";
<?php
$arr=array(
"name" => "Krish",
"age" => "27",
"COD" => ""
);
print_r(array_map(function($i){return (''===$i)?0:$i;},$arr));
?>