按照索引奇偶分割数组

21

我有一个数组:

$array = array(a, b, c, d, e, f, g);

我想将它分成两个数组,取决于索引是偶数还是奇数,就像这样:

$odd = array(a, c, e, g);

$even = array(b, d, f);

提前感谢!


bdf 的键是 135,你确定它们不应该是 $odd 吗? - Krycke
10个回答

44

使用匿名函数和array_walk的一种解决方案:


One solution, using anonymous functions and `array_walk`:
$odd = array();
$even = array();
$both = array(&$even, &$odd);
array_walk($array, function($v, $k) use ($both) { $both[$k % 2][] = $v; });

这种方法只需要一次遍历数组就可以将其中的项分离出来,但它有点“巧妙”,并不比传统的冗长方式更好。

$odd = array();
$even = array();
foreach ($array as $k => $v) {
    if ($k % 2 == 0) {
        $even[] = $v;
    }
    else {
        $odd[] = $v;
    }
}

2
我曾经寻找过一些优雅的解决方案,但最终只得到了一个简单而冗长的解决方案。这个方案更易于理解和维护。 - userlond

13

使用array_filter函数 (PHP >= 5.6):

$odd = array_filter($array, function ($input) {return $input & 1;}, ARRAY_FILTER_USE_KEY);
$even = array_filter($array, function ($input) {return !($input & 1);}, ARRAY_FILTER_USE_KEY);

不幸的是,这种技术将在输入数组上进行两次完整的遍历。这个缺点在被接受的答案中并不存在——Jon的两个解决方案都只对输入数组进行了一次遍历。 - mickmackusa

6

作为一个几乎只有一行的代码,我认为这将会是我最喜欢的:

$even = $odd = array();
foreach( $array as $k => $v )  $k % 2  ?  $odd[] = $v  :  $even[] = $v;

还是稍微快一点?速度:

$even = $odd = array();
foreach( $array as $k => $v )  ( $k & 1 ) === 0  ?  $even[] = $v  :  $odd[] = $v;

稍微冗长一些的变体:

$both = array( array(), array() );
// or, if $array has at least two elements:
$both = array();

foreach( $array as $k => $v )  $both[ $k % 2 ][] = $v;
list( $even, $odd ) = $both;

使用 array_chunk 函数:

$even = $odd = array();
foreach( array_chunk( $array, 2 ) as $chunk ){
  list( $even[], $odd[] ) = isset( $chunk[1]) ? $chunk : $chunk + array( null, null );
  // or, to force even and odd arrays to have the same count:
  list( $even[], $odd[] ) = $chunk + array( null, null );
}

如果$array保证有偶数个元素:
$even = $odd = array();
foreach( array_chunk( $array, 2 ) as $chunk )
  list( $even[], $odd[] ) = $chunk;

使用带有array_column的PHP 5.5.0+:

$chunks = array_chunk( $array, 2 );
$even = array_column( $chunks, 0 );
$odd  = array_column( $chunks, 1 );

对于旧版本的PHP也有类似的方法。键值分别为0、2、4……和1、3、5……如果您不喜欢这种方式,可以使用array_values函数:

$even = array_intersect_key( $array, array_flip( range( 0, count( $array ), 2 )));
$odd  = array_intersect_key( $array, array_flip( range( 1, count( $array ), 2 )));

或者

$even = array_intersect_key( $array, array_fill_keys( range( 0, count( $array ), 2 ), null ));
$odd  = array_intersect_key( $array, array_fill_keys( range( 1, count( $array ), 2 ), null ));

1
我喜欢你的array_chunk()array_column()示例,非常简洁。它不需要偶数个元素。 - KIKO Software
谢谢。我想知道我是否仍然能够提出这些解决方案。 :) - biziclop

5

我不确定这是否是最优雅的方式,但它应该能完美运行:

$odd=array();
$even=array();
$count=1;
foreach($array as $val)
{
    if($count%2==1)
    {
        $odd[]=$val;
    }
    else
    {
        $even[]=$val;
    }
    $count++;
}

2

使用array_chunk和array_map的另一个功能性解决方案。当源数组大小为奇数时,最后一行从第二个数组中删除空项。

原始答案: "最初的回答"

list($odd, $even) = array_map(null, ...array_chunk($ar,2));
if(count($ar) % 2) array_pop($even);

1
$odd = [];
$even = [];
while (count($arr)) {
    $odd[] = array_shift($arr);
    $even[] = array_shift($arr);
}

1
请尽量避免只是简单地把代码放在答案中,试着解释它的作用和原因。对于没有相关编码经验的人来说,你的代码可能不明显。请编辑您的回答以包括澄清、上下文并尝试在您的回答中提及任何限制、假设或简化 - Frits
1
不是的。你的回答太简短了,所以它被送到了“低质量审核队列”。我的评论并不是要冒犯你,而且你的回答也没有错,这就是为什么我投票不要将其删除,但是一个基本的解释会很有用。一个简单的句子可以让你的回答质量翻倍,这有助于未来的新用户,并提高你获得+1的机会。这是一个双赢的局面。 - Frits
我是一个简单的人。我不需要投票。我绝对不在乎“质量审核”算法认为我应该做什么。 - Martin
1
@DoubleThink,我懂你的感受。但希望每一个详细解释的答案,即使是琐碎的,都能让 Padawan 学习到更规范的代码。这会给代码大师更多无打扰的编码时间,从而改变世界。 ;) - davmor

1

根据 @Jon 的第二种变体,我制作了以下用于 PHP Smarty v3 模板引擎的代码。这是用于显示新闻/博客的单列或双列模板。

在 MySql 查询后,我会执行以下代码:

if(sizeof($results) > 0) {
    $data = array();
    foreach($results as $k => $res) {
        if($k % 2 == 0) {
            $res["class"] = "even";
            $data["all"][] = $data["even"][] = $res;
        }
        else {
            $res["class"] = "odd";
            $data["all"][] = $data["odd"][] = $res;
        }
    }
}

我使用Smarty语法获得了一个包含3个子数组(包括奇数/偶数类)的数组:

  1. 所有项目 {foreach $data.all as $article}...{/foreach}
  2. 仅奇数项目 {foreach $data.odd as $article}...{/foreach}
  3. 仅偶数项目 {foreach $data.even as $article}...{/foreach}

希望它能帮助一些人......


1
只需循环遍历它们并检查键是偶数还是奇数即可:
$odd = array();
$even = array();
foreach( $array as $key => $value ) {
    if( 0 === $key%2) { //Even
        $even[] = $value;
    }
    else {
        $odd[] = $value;
    }
}

1

$odd = $even = array();
for ($i = 0, $l = count($array ); $i < $l;) { // Notice how we increment $i each time we use it below, by two in total
    $even[] = $array[$i++];
    if($i < $l)
    {
       $odd[] = $array[$i++];
    }
}

$odd = $even = array();
foreach (array_chunk($array , 2) as $chunk) {
    $even[] = $chunk[0];
    if(!empty( $chunk[1]))
    {
       $odd[] = $chunk[1];
    }
}

0
    <?php

$array1 = array(0,1,2,3,4,5,6,7,8,9);
$oddarray = array();
$evenarray = array();

$count = 1;

echo "Original: ";
foreach ($array1 as $value)
 {
    echo "$value";
}

echo "<br> Even: ";

foreach ($array1 as $print) 
{
    if ($count%2==1) 
    {
        $evenarray = $print;
        echo "$print";
    }
    $count++;
}

echo "<br> Odd: ";

foreach ($array1 as $print2) {
    if ($count%2!=1) 
    {
        $oddarray[] = $print2;
        echo "$print2";
    }
    $count++;
}

?>

Output:

Original: 0123456789
Even: 02468
Odd: 13579

请解释你的代码块带来了什么。 - wscourge
有两个循环,一个是用于偶数索引,另一个是用于奇数索引。正如您在输出中看到的那样,它将首先打印原始数组,然后通过第一个循环打印偶数数组,最后通过第二个循环打印奇数数组。因此,该数组已被分成两个部分,即偶数和奇数。 - MD Sulaiman
1
我的意思是,将其作为答案的补充进行解释。 - wscourge
我同意。这个答案缺少教育性的解释。 - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接