【问题标题】:array_slice with continuous sequence php具有连续序列php的array_slice
【发布时间】:2016-11-11 06:26:04
【问题描述】:

美好的一天!

我有13range (1,13) 的数组结构; 有点像

array(1,2,3,4,5,6,7,8,9,10,11,12,13);

$slice=2;
$ignore = 3;

我想要像array(3,4,5,8,9,10,13);这样的数组结构

我尝试使用 array_slice 函数,但我无法按顺序偏移值

array_slice($array,2,13,true); 有没有办法忽略下一个 3 值并将切片添加到下一秒直到最后一个数组,任何本机函数或键都会很棒。

谢谢, 维姬

【问题讨论】:

  • 是否需要保留原数组的索引?

标签: php arrays slice


【解决方案1】:

使用array_merge(),函数一可以连接两个数组切片。这将返回一个新数组。

http://php.net/manual/en/function.array-merge.php

<?php
      $slice = 2;
      $ignore = 3;
      $a = array(1,2,3,4,5,6,7,8,9,10,11,12,13);
      $a = array_merge(array_slice($a, $slice,$ignore),array_merge(array_slice($a, 2* $slice + $ignore,3),  array_slice($a, 3* $slice + 2*$ignore)));
      var_dump($a);
?>

我希望你明白了。 :)

【讨论】:

  • 感谢您的回复,array(9) { [0]=> int(3) [1]=> int(4) [2]=> int(5) [3]=> int (8) [4]=> int(9) [5]=> int(10) [6]=> int(11) [7]=> int(12) [8]=> int(13) } 但是它也返回 11,12?
  • 这样就可以了。抱歉,我没有注意到那个。 $a = array_merge(array_slice($a, 2,3),array_merge(array_slice($a, 7,3), array_slice($a, 12)));
  • 不,我希望它应该是基于我上面设置的变量值的动态
  • 我已经把它改成了动态的。您可以指定 $slice$ignore 。 :)
【解决方案2】:

这是一个函数,它将递归地对 n 长度的数组执行“不对称”切片:

function slice_asym(array $head, $exclude, $include)
{
    $keep = array_slice($head, $exclude, $include);
    $tail = array_slice($head, $exclude + $include);

    return $tail ? array_merge($keep, slice_asym($tail, $exclude, $include)) 
                 : $keep;
}

递归需要一个基本情况,其中递归停止并且所有范围都展开并返回。在我们的例子中,我们希望在 tail 不再包含元素时停止。

array_slice() 总是返回一个数组 - 如果没有元素返回给定的偏移量,array_slice() 返回一个空数组。因此,对于每次递归,我们都希望:

  1. 切出我们想要的元素$keep

  2. 创建一个$tail - 这是数组的一个子集,它排除了我们想要忽略并保留在当前范围内的元素 ($exclude + $include)。

  3. 如果$tail 不为空,则创建新的递归级别。否则停止递归并将所有当前的$keep 元素与下一级递归的结果合并。

在伪代码中,这看起来像:

# step 1: first recursion
head = [1,2,3,4,5,6,7,8,9,10,11,12,13]
keep =     [3,4,5]
tail =           [6,7,8,9,10,11,12,13] # tail not empty

# step 2: second recursion
head =           [6,7,8,9,10,11,12,13] 
keep =               [8,9,10]
tail =                      [11,12,13] # tail not empty

# step 3: third recursion
head =                      [11,12,13] 
keep =                            [13]
tail =                              [] # tail empty: base case met!

# return and merge `keep` elements
[3,4,5] + [8, 9, 10] + [13] -> [3,4,5,8,9,10,13]

根据您的示例,以下调用:

$range  = range(1, 13); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
$sliced = slice_asym($range, 2, 3);

print_r($sliced);

产量:

Array
(
    [0] => 3
    [1] => 4
    [2] => 5
    [3] => 8
    [4] => 9
    [5] => 10
    [6] => 13
)

编辑

如果您使用的是 PHP 5.5 或更高版本,这对于 generator 也是一个很好的用例。

这些很有用,因为:

生成器允许您编写使用 foreach 迭代一组数据的代码,而无需在内存中构建数组,这可能会导致您超出内存限制,或者需要大量的处理时间来生成。

因此,您不必预先创建一个顺序值数组:

相反,您可以编写一个与普通函数相同的生成器函数,不同之处在于生成器不是返回一次,而是生成器可以根据需要多次生成以提供要迭代的值。

我们可以为您的用例实现一个生成器,如下所示:

/**
 * 
 * @param  int $limit  
 * @param  int $exclude
 * @param  int $include
 * @return int
 */
function xrange_asym($limit, $exclude, $include) {

    if ($limit < 0 || $exclude < 0 || $include < 0) {
        throw new UnexpectedValueException(
            '`xrange_asym` does not accept negative values');
    }

    $seq = 1;
    $min = $exclude;
    $max = $exclude + $include;

    while ($seq <= $limit) {

        if ($seq > $min && $seq <= $max) {
            yield $seq;
        }

        if ($seq === $max) {
            $min = $exclude + $max;
            $max = $exclude + $include + $max;
        }

        $seq = $seq + 1;
    }
}

然后像这样使用它:

foreach (xrange_asym(13, 2, 3) as $number) {
    echo $number . ', '; //  3, 4, 5, 8, 9, 10, 13
}

或者使用iterator_to_array() 将整个范围生成为一个数组:

print_r(iterator_to_array(xrange_asym(13, 2, 3)));

希望这会有所帮助:)

【讨论】:

    猜你喜欢
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多