【问题标题】:Split and group array by keys按键拆分和分组数组
【发布时间】:2018-08-27 21:35:05
【问题描述】:

好的,我已经进行了一些搜索,但没有找到答案,所以我要试一试。

我有一个可以输出以下信息的 JSON 文件:

[
    {
        "Contact name(s)": "Person 1, Person 2",
        "Contact title(s)": "Head Comacho, Other Guy",
        "Contact email(s)": "email1@email.net, email@email.com",
        "Contact phone": "123-456-7890, 789-456-1230",
    },
    {   
        "Contact name(s)": "Some Dude",
        "Contact title(s)": "Cool Title",
        "Contact email(s)": "things@email.com",
        "Contact phone": "555-555-5555",
    },
        "Contact name(s)": "",
        "Contact title(s)": "",
        "Contact email(s)": "",
        "Contact phone": "",
    }
]

不幸的是,当数据出现时,这就是数据的命名方式。出我的手。无论如何,我必须得到它,以便拥有多个联系人的这些将分组到他们自己的数组中。这是它需要的样子:

Array
(
    [0] => Array
        (
            [contact_name] => Person 1
            [contact_title] => Head Comacho
            [contact_email] => email1@email.net
            [contact_phone] => 123-456-7890
        )

    [1] => Array
        (
            [contact_name] => Person 2
            [contact_title] => Other Title
            [contact_email] => email@email.com
            [contact_phone] => 789-456-1230
        )
)
Array
(
    [0] => Array
        (
            [contact_name] => Some Dude
            [contact_title] => Cool Title
            [contact_email] => things@email.com
            [contact_phone] => 555-555-5555
        )
)
Array
(
    [0] => Array
        (
            [contact_name] => 
            [contact_title] => 
            [contact_email] => 
            [contact_phone] => 
        )
)

我能够将数据转换为自己的数组,如下所示:

Array
(
    [contact_name] => Array
        (
            [0] => Person 1
            [1] => Person 2
        )

    [contact_title] => Array
        (
            [0] => Head Comacho
            [1] => Other Guy
        )

    [contact_email] => Array
        (
            [0] => email1@email.net
            [1] => email@email.com
        )

    [contact_phone] => Array
        (
            [0] => 123-456-7890
            [1] => 789-456-1230
        )

)

Array
(
 .....etc
)

我将如何像第一个示例一样获得它?

抱歉,如果之前已经回答过这个问题,我不知道该如何表达我的问题。感谢您提供任何和所有帮助。

【问题讨论】:

  • 您是否缺少某些字段?就像现在一样,JSON 无效(最后一个字段上的额外逗号和最后一个对象上缺少左括号)。

标签: php arrays grouping


【解决方案1】:

我认为这个脚本会做你想做的事。我创建了一个函数split_contacts,它获取解码数组中的每个条目,并将值(例如"Person 1, Person 2" => [“Person 1”,“Person 2”])拆分为由对象键索引的数组,其中由preg_replace 按摩成您想要的形式(例如"Contact name(s)" => "contact_name")。请注意,可能可以使用str_replace 而不是preg_replace,但我想让代码在键值格式方面保持灵活。

$json = '[
    {
        "Contact name(s)": "Person 1, Person 2",
        "Contact title(s)": "Head Comacho, Other Guy",
        "Contact email(s)": "email1@email.net, email@email.com",
        "Contact phone": "123-456-7890, 789-456-1230"
    },
    {   
        "Contact name(s)": "Some Dude",
        "Contact title(s)": "Cool Title",
        "Contact email(s)": "things@email.com",
        "Contact phone": "555-555-5555"
    },
    {
        "Contact name(s)": "",
        "Contact title(s)": "",
        "Contact email(s)": "",
        "Contact phone": ""
    }
]';
$arr = json_decode($json, true);

function split_contact($contact) {
    $contacts = array();
    foreach ($contact as $key => $values) {
        $key = strtolower(preg_replace(array('/\(s\)$/', '/\s+/'), array('', '_'), $key));
        foreach (explode(',', $values) as $index => $value) {
            $contacts[$index][$key] = trim($value);
        }
    }
    return $contacts;
}

$newarr = array();
foreach ($arr as $contact) {
    $newarr[] = split_contact($contact);
}

print_r($newarr);

输出:

Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [contact_name] => Person 1
                    [contact_title] => Head Comacho
                    [contact_email] => email1@email.net
                    [contact_phone] => 123-456-7890
                )    
            [1] => Array
                (
                    [contact_name] =>  Person 2
                    [contact_title] =>  Other Guy
                    [contact_email] =>  email@email.com
                    [contact_phone] =>  789-456-1230
                )    
        )    
    [1] => Array
        (
            [0] => Array
                (
                    [contact_name] => Some Dude
                    [contact_title] => Cool Title
                    [contact_email] => things@email.com
                    [contact_phone] => 555-555-5555
                )    
        )    
    [2] => Array
        (
            [0] => Array
                (
                    [contact_name] => 
                    [contact_title] => 
                    [contact_email] => 
                    [contact_phone] => 
                )    
        )    
)

【讨论】:

  • 由于提供的示例数据不需要正则表达式,我宁愿看到更轻松的调用:str_replace()
  • @mickmackusa 我试图保持代码的灵活性......我不知道其余的 OP 数据是什么样的
  • 请对此纯代码答案添加一些解释,以提高其整体教育价值。
  • @mickmackusa 你的愿望......哦等等,不,不是:-)。但这是一个公平的评论,这个答案肯定可以使用一些,我已经这样做了。
【解决方案2】:

如果您可以确保多人的 json 对象始终包含完全相同数量的元素,那么您可以这样做:

<?php

$json = '[
    {"Contact name(s)": "Person 1, Person 2", "Contact title(s)": "Head Comacho, Other Guy", "Contact email(s)": "email1@email.net, email@email.com", "Contact phone": "123-456-7890, 789-456-1230"},
    {"Contact name(s)": "Some Dude", "Contact title(s)": "Cool Title", "Contact email(s)": "things@email.com", "Contact phone": "555-555-5555"},
    {"Contact name(s)": "", "Contact title(s)": "", "Contact email(s)": "", "Contact phone": ""}
]';

$jsonA = json_decode($json, true);

$result = [];
$maxLen = 0;
foreach ($jsonA as &$obj) {
    foreach ($obj as $k => $v) {
        if (!isset($result[$k])) $result[$k] = [];
        foreach (explode(',', $v) as $av) $result[$k][] = trim($av);
        $maxLen = max($maxLen, count($result[$k]));
    }
}

$objects = [];
for ($i=0; $i<$maxLen; $i++) {
    $object = [];
    foreach (array_keys($result) as $k) $object[$k] = isset($result[$k][$i]) ? $result[$k][$i] : '';
    $objects[] = $object;
}

echo '<pre>';
print_r($objects);

打印出来:

Array
(
    [0] => Array
        (
            [Contact name(s)] => Person 1
            [Contact title(s)] => Head Comacho
            [Contact email(s)] => email1@email.net
            [Contact phone] => 123-456-7890
        )

    [1] => Array
        (
            [Contact name(s)] => Person 2
            [Contact title(s)] => Other Guy
            [Contact email(s)] => email@email.com
            [Contact phone] => 789-456-1230
        )

    [2] => Array
        (
            [Contact name(s)] => Some Dude
            [Contact title(s)] => Cool Title
            [Contact email(s)] => things@email.com
            [Contact phone] => 555-555-5555
        )

    [3] => Array
        (
            [Contact name(s)] => 
            [Contact title(s)] => 
            [Contact email(s)] => 
            [Contact phone] => 
        )

)

【讨论】:

    【解决方案3】:

    我找到了这个解决方案:

    $arr = '[
        {
            "Contact name(s)": "Person 1, Person 2",
            "Contact title(s)": "Head Comacho, Other Guy",
            "Contact email(s)": "email1@email.net, email@email.com",
            "Contact phone": "123-456-7890, 789-456-1230"
        },
        {   
            "Contact name(s)": "Some Dude",
            "Contact title(s)": "Cool Title",
            "Contact email(s)": "things@email.com",
            "Contact phone": "555-555-5555"
        },
        {
            "Contact name(s)": "",
            "Contact title(s)": "",
            "Contact email(s)": "",
            "Contact phone": ""
        }
    ]';
    
    $arr = json_decode($arr, true);
    
    foreach ($arr as $row) {
    
        list($m_name, $m_title, $m_email, $m_phone) =
        [explode(',', $row["Contact name(s)"]),explode(',', $row["Contact title(s)"]),
         explode(',', $row["Contact email(s)"]),explode(',', $row["Contact phone"])];
    
        foreach (array_keys($m_name) as $per)
            $result[] = ['name' => $m_name[$per],'title' => $m_title[$per],
                         'email' => $m_email[$per],'phone' => $m_phone[$per]];
    }
    
    var_dump($result);
    

    【讨论】:

      【解决方案4】:

      如果这是我的项目,这就是我会做的事情以及为什么......

      1. 您需要将每个数据子集彼此分开,因此使用$temp 作为外部循环迭代之间的临时存储。必须在每个新的$set 开始时重置临时数组,并且必须将临时数组数据传输到$result 数组以保持原始集合索引。
      2. explode() 最好使用“逗号空格”作为分隔符参数 - 这样就不必调用任何其他函数来清理挥之不去的空格。
      3. 因为您的新旧键是已知的并且是静态的,所以硬编码关联的“翻译”数组将节省大量迭代函数调用,并大大减少代码膨胀。我还认为,这使您可以更轻松地控制密钥准备,并且未来的开发人员将能够很快理解您的代码在做什么。

      代码:(Demo)

      $json = '[
          {"Contact name(s)": "Person 1, Person 2", "Contact title(s)": "Head Comacho, Other Guy", "Contact email(s)": "email1@email.net, email@email.com", "Contact phone": "123-456-7890, 789-456-1230"},
          {"Contact name(s)": "Some Dude", "Contact title(s)": "Cool Title", "Contact email(s)": "things@email.com", "Contact phone": "555-555-5555"},
          {"Contact name(s)": "", "Contact title(s)": "", "Contact email(s)": "", "Contact phone": ""}
      ]';
      $array = json_decode($json, true);
      
      $trans = [
          "Contact name(s)" => "contact_name",
          "Contact title(s)" => "contact_title",
          "Contact email(s)" => "contact_email",
          "Contact phone" => "contact_phone"    
      ];
      
      foreach ($array as $set) {
          $temp = [];
          foreach ($set as $key => $data) {
              foreach (explode(', ', $data) as $index => $value) {
                  $temp[$index][$trans[$key]] = $value;     
              }
          }
          $result[] = $temp;
      }
      var_export($result);
      

      输出:

      array (
        0 => 
        array (
          0 => 
          array (
            'contact_name' => 'Person 1',
            'contact_title' => 'Head Comacho',
            'contact_email' => 'email1@email.net',
            'contact_phone' => '123-456-7890',
          ),
          1 => 
          array (
            'contact_name' => 'Person 2',
            'contact_title' => 'Other Guy',
            'contact_email' => 'email@email.com',
            'contact_phone' => '789-456-1230',
          ),
        ),
        1 => 
        array (
          0 => 
          array (
            'contact_name' => 'Some Dude',
            'contact_title' => 'Cool Title',
            'contact_email' => 'things@email.com',
            'contact_phone' => '555-555-5555',
          ),
        ),
        2 => 
        array (
          0 => 
          array (
            'contact_name' => '',
            'contact_title' => '',
            'contact_email' => '',
            'contact_phone' => '',
          ),
        ),
      )
      

      你会发现这个解决方案不仅简洁、准确、易读;效率也很高,因为整个过程只有一个迭代函数调用(explode())。

      【讨论】:

        猜你喜欢
        • 2018-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多