How to get all values between two array values in php? - php

How can I find all values between two array items (including start and end value)?
Example:
array('3X' => '3X','EX'=> 'EX','VG'=>'VG','G'=>'G','F'=>'F','P'=>'P')
Input: $arr, 'EX', 'F'
Output: 'EX', 'VG', 'G', 'F'
Thanks in advance..

$array = array('3X' => '3X','EX'=> 'EX','VG'=>'VG','G'=>'G','F'=>'F','P'=>'P');
$start = "3X";
$end ="F";
$new_array = [];
$i=0;$go=false;
foreach ($array as $element) {
if($go){
$new_array[$i] = $element;
$i++;
}
if($element==$start){
$go = true;
}
if($element==$end){
$go = false;
}
}
$total_elems_new = count($new_array);
unset($new_array[$total_elems_new-1]);
print_r($new_array);
Testeed on PHP 5.6

Try:
$arr = array('3X' => '3X','EX'=> 'EX','VG'=>'VG','G'=>'G','F'=>'F','P'=>'P');
function findValuesBetweenTwoItems($arr, $start, $end) {
$result = [];
$has_started = false;
foreach ( $arr as $item->$value ) {
if( ( $item != $end && $has_started ) || $item == $start) {
array_push($result, $value);
$has_started = true;
}
if( $item == $end ) {
array_push($result, $value);
return $result;
}
}
$my_values = findValuesBetweenTwoItems($arr, 'EX', 'F');
var_dump($my_values);

Try this:
$array = array('3X' => '3X','EX'=> 'EX','VG'=>'VG','G'=>'G','F'=>'F','P'=>'P');
$arrayKeys = array_keys($array);
$input1 = '3X';
$input2 = 'F';
if(in_array($input1,$array) && in_array($input2,$array)) {
if (array_search($input1, array_keys($array)) >= 0) {
if (array_search($input2, array_keys($array)) >= 0) {
if (array_search($input1, array_keys($array)) < array_search($input2, array_keys($array))) {
echo "Keys in between: ";
for ($i = array_search($input1, array_keys($array)); $i <= array_search($input2, array_keys($array)); $i++) {
echo $array[$arrayKeys[$i]] . ", ";
}
} else {
echo "Keys in between: ";
for ($i = array_search($input2, array_keys($array)); $i <= array_search($input1, array_keys($array)); $i++) {
echo $array[$arrayKeys[$i]] . ", ";
}
}
} else {
echo "Value not found!";
}
} else {
echo "Value not found!";
}
} else{
echo "Value not found!";
}

$from = 'EX';
$to = 'F';
$result = null;
$state = 0;
foreach ($a as $k => $v) {
if (($state == 0 && $from === $v) || ($state == 1 && $to === $v))
$state++;
if ($state && $state < 3)
$result[$k] = $v;
elseif ($state >= 2)
break;
}
if ($state != 2)
$result = null;
The loop searches for the first occurrence of $from, if $state is 0 (initial value), or the first occurrence of $to, if $state is 1. For other values of $state, the loop stops processing.
When either $from, or $to is found, $state is incremented. The values are stored into $result while $state is either 1 ($from is found), or 2 ($to is found).
Thus, $state == 2 means that both values are found, and $result contains the values from the $a array between $from and $to. Otherwise, $result is assigned to null.

Related

How to loop through a foreach until X is found, if not found, look for Y

Sorry if this is a duplicate, I can't figure out what to search for to find the answer.
I have a foreach loop, and in that loop, I'm attempting to test if (A == B). Then once found I break the loop. If (A != B) in an iteration, I test if (X == Y).
My problem is that if (X == Y) is found to be true first, the loop breaks before if (A == B) can be tested.
Is there a better way to accomplish this task?
$variable[1] = ['A' => 'n', 'X' => 'n'];
$variable[2] = ['A' => 'n', 'X' => 'Y'];
$variable[3] = ['A' => 'B', 'X' => 'n'];
$test = 'B';
foreach ($variable as $value) {
if($value['A'] == $test || $value['X'] == "Y") {
echo 'The results: ' . $value['A'];
break;
}
}
// The results for $variable[2] are returned. I need the results for $variable[3] to be returned.
I did have an else statement which worked fine, but I was having to duplicate the output.
Thanks in advance!
The code above is a simplified version of what I'm working on. Here's the code I'm working actually working on.
foreach ($product_xml->products->product_styles as $style => $attribute) {
if(isset($_GET['color']) && $attribute['color'] == $color_selected || $attribute['is_default'] == "1") {
foreach ($attribute as $value){
$imgURL = (string)$value['imgurl'];
$thumburl = (string)$value['thumburl'];
$thumburl_array[(string)$value['side']] = (string)$value['thumburl'];
if (in_array($imgURL, $values)){continue;}
else{
array_push($values, $imgURL);
$imgURL = str_replace("REPLACE_DOMAIN_WITH",IDEQ_INKSOFTAPI_URL_SECURE,$imgURL );
$thumburl = str_replace("REPLACE_DOMAIN_WITH",IDEQ_INKSOFTAPI_URL_SECURE,$thumburl );
$thumburl = str_replace("150.png","500.png",$thumburl );
echo '<img src="'.$imgURL.'" class="pic'.$counter.'" title="'.$value['name'].'">';
$counter++;
}
}
break;
}
}
Use a temporary variable and move the echo to after the foreach.
$variable[1] = ['A' => 'n', 'X' => 'n'];
$variable[2] = ['A' => 'n', 'X' => 'Y'];
$variable[3] = ['A' => 'B', 'X' => 'n'];
$test = 'B';
$output = null;
foreach ($variable as $value) {
if($value['A'] == $test) {
$output = $value['A'];
break;
} else if ($output == null && $value['X'] == "Y") {
$output = $value['X'];
}
}
echo 'The results: ' . $output;
Here is my approximation with a function:
function search($variable, $test){
$alternative = null;
foreach($variable as $value){
if($value['A'] == $test){
return $value['A'];
}
if($value['X'] == 'Y' && $alternative === null){
$alternative = $value['A'];
}
}
return $alternative;
}
It will return first coincidence on A and if not found, first coincidence on X.
This way you only loop through foreach once.
Instead of looping you can use array_column to isolate one column of the array A or X.
Then use in_array to see if you find the $test in the array.
$test = 'B';
$test2 = 'Y';
If(in_array($test, array_column($variable, "A"))){
Echo $test . " Found in A";
}Else if(in_array($test2, array_column($variable, "X"))){
Echo $test2 . " Found in B";
}else{
Echo "none found";
}
https://3v4l.org/dv7Yp
Based off of the response from James Lalor I've come to this solution. If anyone sees a better/more optimal way of handling this, I'd love to hear!
$counter = 1;
$values = array();
$thumburl_array = array();
$found = false;
$find_default = false;
$style_count = count($product_xml->products->product_styles);
for ($i=0; $i < $style_count; $i++) {
if (isset($_GET['color']) && $product_xml->products->product_styles[$i]['color'] == $color_selected) {
$found = true;
} elseif (!$found && !$find_default && $i == $style_count - 1) {
$find_default = true;
$i = 0;
}
if ($find_default && $product_xml->products->product_styles[$i]['is_default'] == '1') {
$found = true;
}
if ($found) {
foreach ($product_xml->products->product_styles[$i] as $value){
$imgURL = (string)$value['imgurl'];
$thumburl = (string)$value['thumburl'];
$thumburl_array[(string)$value['side']] = (string)$value['thumburl'];
if (in_array($imgURL, $values)){continue;}
else{
array_push($values, $imgURL);
$imgURL = str_replace("REPLACE_DOMAIN_WITH",IDEQ_INKSOFTAPI_URL_SECURE,$imgURL );
$thumburl = str_replace("REPLACE_DOMAIN_WITH",IDEQ_INKSOFTAPI_URL_SECURE,$thumburl );
$thumburl = str_replace("150.png","500.png",$thumburl );
echo '<img src="'.$imgURL.'" class="pic'.$counter.'" title="'.$value['name'].'">';
$counter++;
}
}
break;
}
}
Simplified version
$variable[] = ['A' => 'n', 'X' => 'n', 'result' => 'do'];
$variable[] = ['A' => 'n', 'X' => 'Y', 'result' => 're'];
$variable[] = ['A' => 'B', 'X' => 'n', 'result' => 'mi'];
$found = false;
$find_default = false;
$count = count($variable);
$test = 'B';
for ($i=0; $i < $count; $i++) {
if ($variable[$i]['A'] == $test) {
$found = true;
} elseif (!$found && !$find_default && $i == $count - 1) {
$find_default = true;
$i = 0;
continue;
}
if ($find_default && $variable[$i]['X'] == 'Y') {
$found = true;
}
if ($found) {
echo "Resulsts: " . $variable[$i]['result'];
break;
}
}
Thank you all for your feedback, much appreciated. Cheers.

I want to find my value in an array using just 1 foreach

I have an array lets suppose
$myarr = array(
'1',
'2',
'3',
'4-7',
'9',
'10',
)
$search2 = '2';
$search5 = '5';
I want to check both these 2 variables inside my $myarr. The first one can be easily found by using in_array but the $search5 is there inside '4-7' but what will I do to find the value? I don't want 2 foreach because i know I can use explode and then compare the start and end value. Is there a single or double line function that could help me achieve what I need? Thanks
PHP code demo
<?php
ini_set("display_errors", 1);
$search=2;
$result=null;
$myarr = array(
'1',
'2',
'3',
'4-7',
'9',
'10',
);
echo search_in_array($myarr,$search);
function search_in_array($myarr,$search)
{
$result=false;
array_map(function($number) use ($myarr,$search, &$result){
if(preg_match("/^(\d+)\-(\d+)$/", $number,$matches))
{
if(in_array($search,range($matches[1],$matches[2])))
{
$result= true;
}
}
elseif(preg_match("/^(\d+)$/", $number,$matches))
{
if(in_array($search,$myarr))
{
$result= true;
}
}
}, $myarr);
return $result;
}
Just as another answer:
$myarr = [
'1',
'2',
'3',
'4-7',
'9',
'10',
];
$search2 = '2';
$search5 = '5';
$search12 = '12';
function myInArray($needle, $haystack) {
return in_array(
$needle,
array_reduce(
$haystack,
function($incrementor, $value) {
return array_merge($incrementor, (strpos($value, '-') !== false) ? range(...explode('-', $value)) : [(int)$value]);
},
[]
)
);
}
foreach([$search2, $search5, $search12] as $searchValue) {
echo $searchValue, " is ",(myInArray($searchValue, $myarr) ? '' : 'NOT '), "in the array", PHP_EOL;
}
Probably not as efficient, especially when working with larger ranges of values in $myarr, but a slightly different approach
Demo
Here is almost one-liner,
$search = '5';
$matches = explode('-',array_values(preg_grep('/[-]/', $myarr))[0]);
if(in_array($search, $myarr)|| in_array($search,range($matches[0],$matches[1]))){
echo "found";
}else{
echo "not found";
}
I am exploding by - and then creating range with that and checking that with in_array.
Here is working DEMO
<?php
$myarr = ['1', '2', '3', '4-7', '9', '10'];
$search_array = [2, 5];
$search_results = [];
for ($i = 0; $i < count($search_array); $i++) {
$search_results[$search_array[$i]] = array_search($search_array[$i], $myarr);
if (!$search_results[$search_array[$i]]) {
foreach ($myarr as $value) {
if (strpos($value, "-") !== false) {
$data = explode("-", $value);
if ($search_array[$i] >= $data[0] && $search_array[$i] <= $data[1]) {
$search_results[$search_array[$i]] = array_search($value, $myarr);
}
}
}
}
if (!$search_results[$search_array[$i]]) {
unset($search_results[$search_array[$i]]);
}
}
var_dump($search_results);
Obviously using single foreach i cam up with this code to find ... set of data another is for loop not foreach.
#Ali Zia you can also try this logic like below:
<?php
$myarr = array(
'1',
'2',
'3',
'4-7',
'9',
'10',
);
$flag = 0;
$search = '5';
foreach($myarr as $value){
if($value == $search){
$flag = 1;
break;
}
else if(strpos($value, "-")){
$numberRange = explode("-", $value);
if($numberRange[0] <= $search && $numberRange[1] >= $search){
$flag = 1;
break;
}
}
}
if($flag == 1){
echo "yes number found in the array";
}
else{
echo "sorry not found";
}
Just for the sake of using range() and argument unpacking, because none of the other answers do:
function in_array_range($needle, array $haystack) {
if (in_array((int) $needle, $haystack, true)) {
return true;
}
$haystack = array_map(
function($element) {
return strpos($element, '-')
? range(... explode('-', $element, 2))
: (int) $element;
},
$haystack
);
foreach ($haystack as $element) {
if (is_array($element) && in_array((int) $needle, $element, true)) {
return true;
}
}
return false;
}
The function below returns the index of $needle in $haystack or -1 if no such element has been found.
function find(array $haystack, $needle) {
for ($i = 0; $i < count($haystack); $i++) {
$parts = explode("-", $haystack[$i]);
if (count($parts) == 2) {
if ($needle >= $parts[0] && $needle <= $parts[1]) {
return $i;
}
}
else if ($needle == $parts[0]) {
return $i;
}
}
return -1;
}
The function assumes that $array only contains a single non-negative integer or two non-negative integers separated by a dash.
You can now collect the indices like this:
$indices = array();
foreach ($searchValues as $searchValue) {
$indices[] = find($myarr, $searchValue);
}
Try with following code :
$myarr = array('1','2','3','4-7','9','10');
$search = 1; // Try with 5
$flag1 = false;
foreach($myarr as $number){
if(!is_numeric($number)){
list($start,$end) = explode("-",$number);
if($search >=$start && $search <=$end ){
echo $search .' Found';
}
}else if($flag1 == false){
if(in_array($search,$myarr)){
echo $search .' Found';
$flag1 = true;
}
}
}
Working Demo
I know the answer has already been accepted but here is my approach w/ and w/o using foreach.
(See demo).
With foreach :
<?php
$value = 3;
foreach($myarr as $myval){
list($start, $end) = strpos($myval, '-') ? explode('-', $myval) : [$myval, $myval];
if($value >= $start && $value <= $end){
echo $value . ' found between "' . $start . '" & "' . $end . '" !' . "\n";
}
}
Without foreach, "one line" code :
<?php
$value = 5;
$trueValues = [1,5];
$falseValues = [5, 7, 8];
var_dump(!count(array_diff($trueValues,array_reduce($myarr,function($arr, $item){return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);},[]))));
var_dump(!count(array_diff($falseValues,array_reduce($myarr,function($arr, $item){return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);},[]))));
var_dump(in_array($value, array_reduce($myarr, function($arr, $item){return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);}, array())));
Unfolded :
<?php
var_dump(
!count(
array_diff(
$trueValues,
array_reduce(
$myarr,
function($arr, $item){
return $arr + (strpos($item, '-') ? range(...explode('-', $item)) : [$item]);
},
[]
)
)
)
);
EDIT : Didn't know the ellipsis operator, thank you #Mark Baker

Inserting an item after specific array pattern

I would like to insert an item after a specific pattern. In my case I would like to insert x after every second a in an array. After six'th a my code does not work properly:
$array = array("a","a","a","a","a","a","b","a","a");
$out = array();
foreach ($array as $key=>$value){
$out[] = $value; // add current letter to new array
if($value=='a' && $array[$key-1]=='a' && $out[$key] !='x'){ // check if current and last letter are a
$out[] = 'x'; // if so add an x to the array
}
}
print_r($out);
Correct answer at the end
Is it that what are you looking for?
<?php
$array = array("a","a","a","a","a","a","b","a","a");
foreach ($array as $key => $value){
if ($key == 0 || $key == 1) {
$array[$key] = $value;
} elseif($array[$key-1] == 'a' && $array[$key-2] == 'a' && $array[$key] == 'a') {
$array[$key] = 'x';
} else {
$array[$key] = $value;
}
}
$count = count($array);
if ($array[$count-1] == 'a' && $array[$count-2] == 'a') {
$array[] = 'x';
}
print_r($array);
?>
If I understand correctly, after 2 a you want to put x into new array.
UPDATE
Please check now. There will be added a new element x if last two are a in array.
With exceptions, but still working:
<?php
$array = array("a","a","a","a","a","a","b","a","a");
foreach ($array as $key => $value){
if($array[$key-1] == 'a' && $array[$key-2] == 'a' && $array[$key] == 'a') {
$array[$key] = 'x';
}
}
$count = count($array);
if ($array[$count-1] == 'a' && $array[$count-2] == 'a') {
$array[] = 'x';
}
print_r($array);
?>
UPDATE - Correct code
I think code below will fit all your needs:
<?php
$arr = array("a","w","a","d","a","a","b","a","a", "w");
$arr_count = count($arr);
for ($i = 0; $i < $arr_count; $i++){
if (!empty($arr[$i+1]) && $arr[$i] == $arr[$i+1]) {
$first_half = array_slice($arr, 0, $i+2);
$second_half = array_slice($arr, $i+2, $arr_count);
if (count($second_half) > 0) {
$arr = array_merge($first_half, ["x"], $second_half);
}
}
}
$count = count($arr);
if ($arr[$count-1] == 'a' && $arr[$count-2] == 'a') {
$arr[] = 'x';
}
print_r($arr);
?>
As it was mentioned in the comment, you sure can use regular expression in this particular situation:
$pattern = '/a{2}/';
$replacement = '$0x';
$out = str_split(preg_replace(
$pattern,
$replacement,
implode('', $array)
));
Basically, we gluing the characters together (using implode) to form the string and then replacing every "aa" with "aax". After that we split string back to the array using str_split.
Here is demo.

Comma separated string to parent child relationship array php

I have a comma separated string like
$str = "word1,word2,word3";
And i want to make a parent child relationship array from it.
Here is an example:
Try this simply making own function as
$str = "word1,word2,word3";
$res = [];
function makeNested($arr) {
if(count($arr)<2)
return $arr;
$key = array_shift($arr);
return array($key => makeNested($arr));
}
print_r(makeNested(explode(',', $str)));
Demo
function tooLazyToCode($string)
{
$structure = null;
foreach (array_reverse(explode(',', $string)) as $part) {
$structure = ($structure == null) ? $part : array($part => $structure);
}
return $structure;
}
Please check below code it will take half of the time of the above answers:
<?php
$str = "sports,cricket,football,hockey,tennis";
$arr = explode(',', $str);
$result = array();
$arr_len = count($arr) - 1;
$prev = $arr_len;
for($i = $arr_len; $i>=0;$i--){
if($prev != $i){
$result = array($arr[$i] => $result);
} else {
$result = array ($arr[$i]);
}
$prev = $i;
}
echo '<pre>',print_r($result),'</pre>';
Here is another code for you, it will give you result as you have asked :
<?php
$str = "sports,cricket,football,hockey,tennis";
$arr = explode(',', $str);
$result = array();
$arr_len = count($arr) - 1;
$prev = $arr_len;
for($i = $arr_len; $i>=0;$i--){
if($prev != $i){
if($i == 0){
$result = array($arr[$i] => $result);
}else{
$result = array(array($arr[$i] => $result));
}
} else {
$result = array ($arr[$i]);
}
$prev = $i;
}
echo '<pre>',print_r($result),'</pre>';

getting the even index of a string

hey guys im trying to get the even indexes of a string from the db then save them in a variable then echo. but my codes seems doesnt work. please help. here it is
require_once('DBconnect.php');
$school_id = '1';
$section_id = '39';
$select_pk = "SELECT * FROM section
WHERE school_id = '$school_id'
AND section_id = '$section_id'";
$query = mysql_query($select_pk) or die (mysql_error());
while ($row = mysql_fetch_assoc($query)) {
$public_key = $row['public_key'];
}
if ($public_key) {
$leng_public_key = strlen($public_key);
$priv_key_extract = "";
$array_pki = array();
for ($i=0; $i <=$leng_public_key-1 ; $i++) {
array_push($array_pki,$public_key[$i]);
}
foreach ($array_pki as $key => $value) {
if($key % 2 == 0) {
$priv_key_extract += $public_key[$key];
} else {
$priv_key_extract ="haiiizzz";
}
}
}
echo $priv_key_extract;
as you can see im trying to use modulo 2 to see if the index is even.
I have updated your code as below, it will work now :
<?php
$public_key = 'A0L8V1I5N9';
if ($public_key) {
$leng_public_key = strlen($public_key);
$priv_key_extract = "";
$array_pki = array();
for ($i=0; $i <=$leng_public_key-1 ; $i++) {
array_push($array_pki,$public_key[$i]);
}
foreach ($array_pki as $key => $value) {
//Changed condition below $key % 2 ==0 => replaced with $key % 2 == 1
if($key % 2 == 1) {
// Changed concatenation operator , += replaced with .=
$priv_key_extract .= $public_key[$key];
} /*else {
//Commented this as it is getting overwritten
$priv_key_extract ="haiiizzz";
}*/
}
}
echo $priv_key_extract;
?>
Try this function
function extractKey($key) {
if (empty($key) || !is_string($key)) return '';
$pkey = '';
for ($i=0;$i<strlen($key);$i++) {
if ($i % 2 == 0) {
$pkey .= $key[$i];
}
}
return $pkey;
}
echo extractKey('12345678'); # => 1357

Categories