2

i have array object and want get 2 previous and and 2 next array group by specific key.

Array
(
    [467] => stdClass Object
        (
            [id] => 467
            [user_id] => 1
        )

    [468] => stdClass Object
        (
            [id] => 468
            [user_id] => 1
        )

    [469] => stdClass Object
        (
            [id] => 469
            [user_id] => 1
        )

    [474] => stdClass Object
        (
            [id] => 474
            [user_id] => 1
        )

    [475] => stdClass Object
        (
            [id] => 475
            [user_id] => 1
        )

    [479] => stdClass Object
        (
            [id] => 479
            [user_id] => 1
        )

    [480] => stdClass Object
        (
            [id] => 480
            [user_id] => 1
        )
)

If key define 474 will result:

  • Previous array group from key 469 and 468
  • Next array group from key 475 and 479
  • If don't have previous and next array, i want no result

I try this method, but not working.

$val = 474;
$currentKey = array_search($val, $array);

$before = (isset($array[$currentKey - 2])) ? $array[$currentKey - 2] :
$after = (isset($array[$currentKey + 2])) ? $array[$currentKey + 2] : $array[0];

var_dump($before, $after);

Please help.

4
  • And what do you want to happen if there aren't 2 elements available (before or after) the targeted element? Are we going "around the clock"? "not working" because there is an error or is providing incorrect results? or no results? Commented Nov 24, 2017 at 2:37
  • 1
    I want no result., Commented Nov 24, 2017 at 2:39
  • Please add that relevant detail to your question as an edit. You mean you want the whole thing to fail? or might you accept 1 leading element and 2 trailing elements? This will determine the correct function to call. Commented Nov 24, 2017 at 2:42
  • Okay, thanks, i add If don't have previous and next array, i want no result Commented Nov 24, 2017 at 2:44

2 Answers 2

5

What my method will do is, search for the $key value and return its offset in the array. You were using array_search() on the input array's values, so that's where it fell flat.

Then if the offset value is not false, I attempts to slice the 5 desired subarrays from the input array. If it doesn't return 5, then it fails.

The second code will not trigger a failure if the collection of subarrays is less than 5.

Code: (Demo)

$array=[
    467=>(object)['id'=>467,'user_id'=>1],
    468=>(object)['id'=>468,'user_id'=>1],
    469=>(object)['id'=>469,'user_id'=>1],
    474=>(object)['id'=>474,'user_id'=>1],
    475=>(object)['id'=>475,'user_id'=>1],
    479=>(object)['id'=>479,'user_id'=>1],
    480=>(object)['id'=>480,'user_id'=>1]
];

$key=480;

// require 5 subarrays or none:
if(($offset=array_search($key,array_keys($array)))<2 || sizeof($result=array_slice($array,$offset-2,5))!=5){
    echo "Fail";    
}else{
    var_export($result);
}

echo "\n---\n";

// allow any number of subarrays up to 5:
if(($offset=array_search($key,array_keys($array)))===false){
    echo "Fail";    
}else{
    // adjust $offset and $length values to handle array "overflow"
    if($offset<2){
        $length=$offset+3;
    }elseif(($diff=sizeof($array)-$offset)<3){
        $length=$diff+2;
    }else{
        $length=5;
    }
    $offset=max(0,$offset-2);
    var_export(array_slice($array,$offset,$length));
}

Output:

Fail
---
array (
  0 => 
  stdClass::__set_state(array(
     'id' => 475,
     'user_id' => 1,
  )),
  1 => 
  stdClass::__set_state(array(
     'id' => 479,
     'user_id' => 1,
  )),
  2 => 
  stdClass::__set_state(array(
     'id' => 480,
     'user_id' => 1,
  )),
)

Here is a visual representation and some more explanation of what the second method is doing:

The following explanation uses a 6-element array to demonstrate the calculations.

I = 'elements labeled by their indices'
S = 'the slice'
T = 'target index'
L = 'length of slice'

I   ST  ST  ST  ST  ST  ST            When $target index is:
0   ╗0  ╗   ╗                         0, then $offset=0 and $length=3
1   ║   ║1  ║   ╗                     1, then $offset=0 and $length=4
2   ╝   ║   ║2  ║   ╗                 2, then $offset=0 and $length=5
3       ╝   ║   ║3  ║   ╗             3, then $offset=1 and $length=5
4           ╝   ║   ║4  ║             4, then $offset=2 and $length=4
5               ╝   ╝   ╝5            5, then $offset=3 and $length=3
L:  3   4   5   5   4   3
Sign up to request clarification or add additional context in comments.

5 Comments

I think you should check if the offset is less than 2.
great code, but how to make still get result if key define468 or 479
@Opsional now you want it to possibly return less than 5 subarrays? I can code it that way if you wish.
only possibilty if me or some one need it.,
1

Since your array is not in the sequence, try this one Demo.

$arr = array(   467 => (object) ['id' => 467, 'user_id' => 1],
                468 => (object) ['id' => 468, 'user_id' => 1],
                469 => (object) ['id' => 469, 'user_id' => 1],
                474 => (object) ['id' => 474, 'user_id' => 1],
                475 => (object) ['id' => 475, 'user_id' => 1],
                479 => (object) ['id' => 479, 'user_id' => 1],
                480 => (object) ['id' => 480, 'user_id' => 1],);
$find = 474;
$before2 = $before1 = $next1 = $next2 = array(); 
$flag = false;     

foreach ($arr as $key => $val) {
        if($key == $find) {
            $flag = true;    
        }
        if(!$flag) {
            if(!empty($before1)){
                $before2 = $before1;                
            }
            $before1 = $val;
        }
        if($key != $find) {
            if($flag && empty($next2)){
                if(!empty($next1)){
                    $next2 = $next1;
                }
                $next1 = $val;                   
            }
            if(!empty($next2)){
                break;
            }    
        }

}     

if($flag) {
    echo "matching values  =>";
    var_dump($before2);
    var_dump($before1);
    var_dump($next1);
    var_dump($next2);
} else {
    echo "given index not found!";
}

4 Comments

There is a small correction on the $next2 variable. It was coming wrong. It is corrected now in the last Edit.
There is a lot of non-sense in this answer. You are over-writing and empty-checking variables on each iteration. There are way too many conditionals. This is convoluted and unnecessarily so. No one should be using this method. Definitely not best practice. You haven't even bothered to include an explanation.
@mickmackusa Did you check your answer with 468 and 479? your Code giving wrong answer. In my answer, there are only 2 variables getting over written.
You were right. I fixed those $offset and $length issues with the second script that I hastily wrote when the OP extended the question requirements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.