【问题标题】:Get previous and next array by key from array object从数组对象中按键获取上一个和下一个数组
【发布时间】:2017-11-24 02:28:16
【问题描述】:

我有一个数组对象,想通过特定的键获得 2 个前一个和 2 个下一个数组组。

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
        )
)

如果键定义 474 将导致:

  • 键 469 和 468 中的上一个数组组
  • 键 475 和 479 中的下一个数组组
  • 如果没有上一个和下一个数组,我不想要结果

我尝试了这种方法,但不起作用。

$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);

请帮忙。

【问题讨论】:

  • 如果没有 2 个可用的元素(在目标元素之前或之后),您希望发生什么?我们要“全天候”吗? “不工作”是因为有错误或提供了不正确的结果?还是没有结果?
  • 我不想要结果,
  • 请将相关详细信息添加到您的问题中作为编辑。你的意思是你想让整个事情都失败?还是您可以接受 1 个前导元素和 2 个尾随元素?这将确定要调用的正确函数。
  • 好的,谢谢,我加If don't have previous and next array, i want no result

标签: php arrays


【解决方案1】:

由于你的数组不在序列中,试试这个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!";
}

【讨论】:

  • $next2 变量有一个小的修正。它来错了。现在在上次编辑中更正了。
  • 这个答案有很多废话。您在每次迭代时都在覆盖和检查变量。有太多的条件。这是令人费解且不必要的。没有人应该使用这种方法。绝对不是最佳实践。你甚至都懒得解释。
  • @mickmackusa 你用 468 和 479 检查你的答案了吗?你的代码给出了错误的答案。在我的回答中,只有 2 个变量被覆盖。
  • 你是对的。我用我在 OP 扩展问题要求时匆忙编写的第二个脚本修复了那些 $offset$length 问题。
【解决方案2】:

我的方法是搜索$key 值并在数组中返回它的offset。您在输入数组的值上使用了array_search(),所以这就是它失败的地方。

然后,如果offset 值不为假,我会尝试从输入数组中分割出 5 个所需的子数组。如果不返回 5,则失败。

如果子数组的集合小于5,第二个代码不会触发失败。

代码:(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));
}

输出:

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,
  )),
)

这是一个视觉表示和对第二种方法的更多解释:

以下解释使用 6 元素数组来演示计算。

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

【讨论】:

  • 我认为你应该检查偏移量是否小于2。
  • 很好的代码,但是如果键定义468479 时如何使仍然得到结果
  • @Opsional 现在您希望它可能返回少于 5 个子数组吗?如果你愿意,我可以这样编码。
  • 只有在我或其他人需要时才有可能。,
猜你喜欢
  • 2015-11-14
  • 1970-01-01
  • 2020-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-06
  • 2018-03-16
  • 1970-01-01
相关资源
最近更新 更多