为了账号安全,请及时绑定邮箱和手机立即绑定

如何订购“斑马”数组,以便每个键都有一个备用值(1、0)

如何订购“斑马”数组,以便每个键都有一个备用值(1、0)

PHP
森栏 2022-07-29 10:16:03
如果你有这个 PHP 数组:$args = array(    'a' => array(        'zebra' => 1,    ),    'b' => array(        'zebra' => 0,    ),    'c' => array(        'zebra' => 0,    ),    'd' => array(        'zebra' => 0,    ),    'e' => array(        'zebra' => 1,    ),);有没有办法通过“斑马”键值在算法上改变这个数组的顺序,但不是“增量”(0,0,0,1,1),它们会交替(0,1,0,1 ,0)。因此,使用上面的示例,所需的完成数组将如下所示:$ordered_args = array(    'b' => array(        'zebra' => 0,    ),    'a' => array(        'zebra' => 1,    ),    'c' => array(        'zebra' => 0,    ),    'e' => array(        'zebra' => 1,    ),    'd' => array(        'zebra' => 0,    ),);任何额外的重复项都应附加到末尾,因此解决方案应允许其他数组,例如具有斑马值的数组,例如 (1,1,1,1,0,0),这将导致 (0,1,0, 1,1,1)我根本想不通这个!编辑:我尝试通过这个类似但不同的 question使用 usort 来做到这一点,但答案是否定的,所以我正在寻找一个编程解决方案(没有 usort)。
查看完整描述

4 回答

?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

同样的想法是将输入分成 1 和 0,然后只要还有一些东西要输出,就输出 0 和 1。每次输出一个值时,数组都会减少,这会一直持续到两个列表都是空的,所以应该处理不平衡的列表......


$temp = [ 0 => [], 1 => []];


foreach($args as $key=>$value){

    $temp[$value['zebra']][] = $key;

}


$output = [];

while ( !empty($temp[0]) || !empty($temp[1]) )   {

    if ( !empty($temp[0]) )   {

        $next = array_shift($temp[0]);

        $output [$next] = $args[$next];

    }

    if ( !empty($temp[1]) )   {

        $next = array_shift($temp[1]);

        $output [$next] = $args[$next];

    }

}


查看完整回答
反对 回复 2022-07-29
?
翻阅古今

TA贡献1780条经验 获得超5个赞

这是array_map在单独的数组中抓取 1 和 0 后使用的解决方案:


$args0 = array_filter($args, function ($arg) {

  return $arg['zebra'] === 0;

});

$args1 = array_filter($args, function ($arg) {

  return $arg['zebra'] === 1;

});


$result = array_merge(...array_map(static function ($arg0Key, $arg1Key) use ($args0, $args1) {

  if ($arg0Key !== null) {

    $result[$arg0Key] = $args0[$arg0Key];

  }

  if ($arg1Key !== null) {

    $result[$arg1Key] = $args1[$arg1Key];

  }

  return $result;

}, array_keys($args0), array_keys($args1)));


print_r($result);

演示:https ://3v4l.org/sfqeq


注意:使用两个array_filter分隔值看起来不错,但循环$args两次;如果初始数组可能有点大,则更喜欢简单的循环。不过,这不是答案的相关部分。


查看完整回答
反对 回复 2022-07-29
?
德玛西亚99

TA贡献1770条经验 获得超3个赞

我可以建议您使用带有比较计数的解构。


第一步,您可以使用zebra = 1和 with收集所有索引zebra = 0:


$zeros = [];

$ones = [];


foreach($args as $let=>$arg){

    if ($arg['zebra'] === 1) {

        $ones[] = $let;

    } else if ($arg['zebra'] === 0) {

        $zeros[] = $let;

    }

}

现在您可以构造结果数组,例如:


if(abs(count($zeros) - count($ones)) === 1) {    // if their difference equal to 1

    if (count($ones) > count($zeros)){           // if $ones is bigger

        foreach($zeros as $ind=>$let){ 

            $res[$ones[$ind]] = ['zebra' => 1];

            $res[$let]        = ['zebra' => 0];  

            $tmp = $ind;

        } 

        $res[$ones[$tmp+1]] = ['zebra' => 1];

    } else if (count($ones) < count($zeros)){      // if $zeros is bigger

        foreach($ones as $ind=>$let){ 

            $res[$zeros[$ind]] = ['zebra' => 0];

            $res[$let]        = ['zebra' => 1];  

            $tmp = $ind;

        } 

        $res[$zeros[$tmp+1]] = ['zebra' => 0];

    }

}

输出:


Array

(

    [b] => Array

        (

            [zebra] => 0

        )


    [a] => Array

        (

            [zebra] => 1

        )


    [c] => Array

        (

            [zebra] => 0

        )


    [e] => Array

        (

            [zebra] => 1

        )


    [d] => Array

        (

            [zebra] => 0

        )


)

演示


如果在 (1,0,1,0,0) 的情况下需要结果,请使用下一个构造函数:


    if (count($ones) > count($zeros)){

        foreach($ones as $ind=>$let){ 

            if (isset($zeros[$ind])) $res[$zeros[$ind]] = ['zebra' => 0]; 

            $res[$let]        = ['zebra' => 1];  

        }  

    } else if (count($zeros) > count($ones)){

        foreach($zeros as $ind=>$let){ 

            $res[$let]        = ['zebra' => 0];  

            if (isset($ones[$ind])) $res[$ones[$ind]] = ['zebra' => 1]; 

        }  

    }

输出:


Array

(

    [b] => Array

        (

            [zebra] => 0

        )


    [a] => Array

        (

            [zebra] => 1

        )


    [d] => Array

        (

            [zebra] => 0

        )


    [c] => Array

        (

            [zebra] => 1

        )


    [e] => Array

        (

            [zebra] => 0

        )


)


查看完整回答
反对 回复 2022-07-29
?
宝慕林4294392

TA贡献2021条经验 获得超8个赞

好吧,您可以收集0一个数组中的所有1s' 和另一个数组中的所有 s',然后只需将它们交替添加到新数组中并进行布尔flag检查。


伪代码:


ones = []

zeroes = []


for($args as key => value)

    value['key'] = key // to preserve the key as well for later restoration

    if(value['zebra'] == 1)

       ones.push(value)

    else 

       zeroes.push(value)



result = []

flag = true // to decide to pop from ones or zeroes



while(sizeof(ones) > 0 || sizeof(zeroes) > 0){

    if(sizeof(ones) == 0 || flag === false){

        element = zeroes.pop()

        result[element['key']] = ['zebra' => element['zebra']]

    }else if(sizeof(zeroes) == 0 || flag){

        element = ones.pop()

        result[element['key']] = ['zebra' => element['zebra']]

    }   


    flag = !flag // to alternately add from either arrays

}


查看完整回答
反对 回复 2022-07-29
  • 4 回答
  • 0 关注
  • 96 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信