【问题标题】:PHP SPLIT array based on key range基于键范围的PHP SPLIT数组
【发布时间】:2016-11-20 08:52:54
【问题描述】:

我有一个数组。

大批 ( [初始] => MSS [小时] => 5.2 [row_checker_1] => 1 [项目名称_1] => KGD001 [project_shortcode_1] => KGD001 [5_1] => 23 [6_1] => 3.3 [4_1] => 23.2 [remarks_1] => 继续 [task_id] => 76 [row_checker_2] => 2 [项目名称_2] => DG001 [project_shortcode_2] => DG001 [5_2] => 1.1 [6_2] => 2.2 [4_2] => 3.1 [remarks_2] => 继续 )

现在我想拆分所有元素的上限键是“project_shortcode_1”,下限键是备注_1。

所以,新数组应该是这样的:

大批 ( [5_1] => 23 [6_1] => 3.3 [4_1] => 23.2 )

【问题讨论】:

  • 你知道数组中的键可以有不同的顺序吗?
  • 也许您只需要带有键 NUMBER_1 的值?
  • 如果有 NUMBER_1 个可能,这将是完美的解决方案。
  • 这是可能的,但我在这里没有看到任何代码尝试。如果您认为我们会为您编写代码,那您就错了。
  • 我只是想知道,是否可以基于php数组索引键?

标签: php arrays


【解决方案1】:

使用带有标志ARRAY_FILTER_USE_KEY 的array_filter 来使用数组键,并与获取所需键所需的逻辑进行比较。它适用于 PHP 5.6。

$arr = array ( "initial" => "MSS",
        "hour" => 5.2,
        "row_checker_1" => 1,
        "project_name_1" => "KGD001",
        "project_shortcode_1" => "KGD001",
        "5_1" => 23,
        "6_1" => 3.3,
        "4_1" => 23.2,
        "remarks_1" =>  "on going",
        "task_id" => 76,
        "row_checker_2" => 2,
        "project_name_2" => "DG001",
        "project_shortcode_2" => "DG001",
        "5_2" => 1.1,
        "6_2" => 2.2,
        "4_2" => 3.1,
        "remarks_2" =>   "on going",
    );

// PHP > 5.6
$result = array_filter($arr, function($k){
    $var = explode('_', $k);
    return is_numeric($var[0]) && $var[1]==1;
}, ARRAY_FILTER_USE_KEY);

【讨论】:

  • 这是一篇好文章,但我只想指出 "7_1_gotcha"=> 666 将符合结果数组的条件,但不应该存在。这是一个完全虚构的数组元素(猴子扳手)——我不知道这个方法漏洞实际上会造成麻烦的可能性有多大。我的观点是:这是不使用从头到尾的正则表达式模式的缺点。
  • 好点。优化过滤条件 (count($var) == 2) 可以避免该漏洞。我认为选择正则表达式模式解决方案是需求和性能问题。
  • 我保证在发表此评论后让你一个人呆着;) ..."2e7_1" => 666 也将通过。这不是explode() 的错,而是is_numeric() 的宽容倾向。
  • 总是欢迎改进! :) 如果只需要整数,则使用 intval($var) == $var 检查可能会完成这项工作。
  • 应该可以的。
【解决方案2】:

如果您需要的是一个包含所有范围 NUMBER_N 的多维数组,请使用类似这样的内容(从 Dmitriy Demir 答案扩展):

$myArray = array(
    'initial' => 'MSS',
    'hour' => '5.2',
    'row_checker_1' => '1',
    'project_name_1' => 'KGD001',
    'project_shortcode_1' => 'KGD001',
    '5_1' => '23',
    '6_1' => '3.3',
    '4_1' => '23.2',
    'remarks_1' => 'on going',
    'task_id' => '76',
    'row_checker_2' => '2',
    'project_name_2' => 'DG001',
    'project_shortcode_2' => 'DG001',
    '5_2' => '1.1',
    '6_2' => '2.2',
    '4_2' => '3.1',
    'remarks_2' => 'on going'
);

function splitRange($a){
    $newArray = array();
    foreach ($a as $k => $v) {
        $rightFormat = preg_match('/^\d+_(\d+)$/', $k, $index);
        if ($rightFormat)
            $newArray[$index[1]][$k] = $v;
    }
    return $newArray;
}

print_r(splitRange($myArray));

结果会是这样的:

    Array
(
    [1] => Array
        (
            [5_1] => 23
            [6_1] => 3.3
            [4_1] => 23.2
        )

    [2] => Array
        (
            [5_2] => 1.1
            [6_2] => 2.2
            [4_2] => 3.1
        )

)

作为N 来自NUMBER_N 数组的索引。

【讨论】:

    【解决方案3】:

    由于您在 cmets 中提到您希望获取格式为 NUMBER_1 的所有值,我认为您需要遍历数组并使用正则表达式检查值名称,然后将值添加到如果它们符合条件,则为新数组。我会这样做:

    $myArray = array(
        'initial' => 'MSS',
        'hour' => '5.2',
        'row_checker_1' => '1',
        'project_name_1' => 'KGD001',
        'project_shortcode_1' => 'KGD001',
        '5_1' => '23',
        '6_1' => '3.3',
        '4_1' => '23.2',
        'remarks_1' => 'on going',
        'task_id' => '76',
        'row_checker_2' => '2',
        'project_name_2' => 'DG001',
        'project_shortcode_2' => 'DG001',
        '5_2' => '1.1',
        '6_2a' => '2.2',
        '4_2' => '3.1',
        'remarks_2' => 'on going'
    );
    
    $newArray = array();
    foreach ($myArray as $k => $v) {
        $rightFormat = preg_match('/^\d+_\d+$/', $k);
        if ($rightFormat)
            $newArray[$k] = $v;
    }
    print_r($newArray);
    

    print_r 在这种情况下的结果是:

    数组 ( [5_1] => 23 [6_1] => 3.3 [4_1] => 23.2 [5_2] => 1.1 [6_2] => 2.2 [4_2] => 3.1)

    如果下划线后面的数字应始终为 1,则将正则表达式从 /^\d+_\d+$/ 更改为 /^\d+_1$/

    您可以到处玩一下,看看 regex 是如何工作的 here

    PS:为方便起见,我将所有值都设置为字符串。随意修改。

    【讨论】:

    • 我稍微修改了正则表达式:从 /\d+_\d//^\d+_\d$/,这样可以确保像 5_1aa5_1 这样的键不会进入新数组。跨度>
    【解决方案4】:

    基于正则表达式的解决方案似乎适合这个问题。

    preg_grep() 是一个函数,旨在对数组中的每个值应用正则表达式过滤器。对于这种情况,我需要进行更多调整,因为必须过滤键。

    单线

    $output=array_intersect_key($input,array_flip(preg_grep("/^\d+_1$/",array_keys($input)))));
    /* array (
          '5_1' => 23,
          '6_1' => 3.3,
          '4_1' => 23.2,
        )*/
    

    这里是逐步操作数组...

    array_keys($input);  // create array with input keys as values
    /* array (
          0 => 'initial',
          1 => 'hour',
          2 => 'row_checker_1',
          3 => 'project_name_1',
          4 => 'project_shortcode_1',
          5 => '5_1',
          6 => '6_1',
          7 => '4_1',
          8 => 'remarks_1',
          9 => 'task_id',
          10 => 'row_checker_2',
          11 => 'project_name_2',
          12 => 'project_shortcode_2',
          13 => '5_2',
          14 => '6_2',
          15 => '4_2',
          16 => 'remarks_2',
       ) */
    
    preg_grep("/^\d+_1$/",array_keys($input));  // filter the input array using regex pattern
    /* array (
          5 => '5_1',
          6 => '6_1',
          7 => '4_1',
       ) */
    
    array_flip(preg_grep("/^\d+_1$/",array_keys($input))); // flip the filtered array
    /* array (
          '5_1' => 5,
          '6_1' => 6,
          '4_1' => 7,
       )*/
    
    array_intersect_key($input,array_flip(preg_grep("/^\d+_1$/",array_keys($input))));  // filter input by comparing keys against filtered array
    /* array (
          '5_1' => 23,
          '6_1' => 3.3,
          '4_1' => 23.2,
       )*/
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2014-08-10
      • 2022-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多