在PHP中合并2个数组,仅保留第一个数组的键

时间:2017-09-21 10:14:54

标签: php arrays array-merge

我有这两个数组:

$list = [
    'fruit' => [],
    'animals' => [],
    'objects' => [],
];

$dataArray = [
    'fruit' => 'apple',
    'animals' => ['dog', 'cat'],
    'asd' => 'bla'
];

我想合并它们,以便最后的$ list是:

[fruit] => Array
    (
        [0] => apple
    )

[animals] => Array
    (
        [0] => dog
        [1] => cat
    )

[objects] => Array
    (
    )

所以,要注意的事情:

  1. 即使'fruit'只有一个元素,仍然是$ list
  2. 中的数组
  3. $ list('asd'键)中缺少的键被忽略
  4. 仍然保留没有值的键,即使是空的
  5. 使用array_merge不起作用:

    $merged = array_merge($list, $dataArray);
    
    [fruit] => apple
    [animals] => Array
        (
            [0] => dog
            [1] => cat
        )
    
    [objects] => Array
        (
        )
    
    [asd] => bla
    

    我设法得到了我想要的东西:

    foreach ($dataArray as $key => $value) {
        if (isset($list[$key])) {
            if (is_array($value)) {
                $list[$key] = $value;
            }
            else {
                $list[$key] = [$value];
            }
    
        }
    
    }
    

    但是我想知道是否有更清洁的方法来做它或其他一些我不知道的PHP功能。

4 个答案:

答案 0 :(得分:4)

您可以通过以下几个步骤实现这一目标:

<h3>{{!item.price ?'No price':item.price}}</h3>

这将返回一个包含第一个数组中所有元素的数组,然后对第二个数组中的键进行过滤。这给你:

$result = array_intersect_key($dataArray, $list);

然后,您可以使用以下方法重新添加第一个数组中缺少的键:

Array
(
  [fruit] => apple
  [animals] => Array
    (
        [0] => dog
        [1] => cat
    )
)

$result + $list; 运算符和+之间的区别在于前者不会使用第二个值覆盖第一个数组。它只会添加任何缺失的元素。

在一行中,这可以解释为:

array_merge

您可以在此处看到它:https://eval.in/865733

编辑:抱歉,完全错过了将元素保存为数组的部分。如果他们总是数组,那么你可以添加一个快速的单行代码,如:

$result = array_intersect_key($dataArray, $list) + $list;

将所有顶级元素强制转换为数组。如果您的逻辑比这更复杂,那么我不确定您是否会找到使用内置函数的方法,抱歉。

答案 1 :(得分:1)

第二条规则({em>“{。{}}($list键中缺少的2.键)被忽略”)告诉我迭代'asd',而不是超过$list。如果$dataArray$dataArray大得多,那么迭代它就会浪费时间,因为它的大多数元素都会被忽略。

你的规则没有解释如何处理$list的元素(如果它们不是空的)(我会假设它们总是数组,否则游戏会发生变化而变得过于复杂而无法提供处理它的通用代码)。

我建议的代码如下:

$list

如果将// Build the result in $result // (you can modify $list as well if you prefer it that way) $result = array(); // 2. keys missing from $list ('asd' key) are simply ignored // iterate over the keys of $list, handle only the keys present in $dataArray foreach ($list as $key => $value) { if (array_key_exists($dataArray, $key)) { // $key is present in $dataArray, use the value from $dataArray $value = $dataArray[$key]; // 1. even if 'fruit' had only one element, is still an array in $list if (! is_array($value)) { $value = array($value); } } // 3. keys with no values are still kept, even if empty // if the key is not present in $dataArray, its value from $list is used $result[$key] = $value; } 块移到if (! is_array($value))块之外,它会将if (array_key_exists())的值转换为数组,这些值不是数组,并且与{中不存在的键相关联{1}}(例如$list)。这样,代码运行后,$dataArray的所有值都是数组。

您的代码也很好。除了迭代$list['objects']而不是$result之外,没有办法让它以更加壮观的方式更快或更容易阅读。我在这里建议的代码只是编写相同内容的另一种方式。

答案 2 :(得分:0)

我的方法将执行3个非常简单的操作:

  1. 运行一个循环,同时使用public class TCPClient { public static String SERVER_IP; public static int SERVER_PORT; private String mServerMessage; // message to send to the server private OnMessageReceived mMessageListener = null; // sends message received notifications private boolean mRun = false; // while this is true, the server will continue running private PrintWriter mBufferOut; // used to send messages public static BufferedReader mBufferIn; // used to read messages from the server Socket socket; public TCPClient(OnMessageReceived listener, String IP, String Port) { mMessageListener = listener; SERVER_IP = IP; SERVER_PORT = Integer.parseInt(Port); } public void sendMessage(String message) { if (socket == null || !socket.isConnected()) { Log.e("313", "Socket Not Connected / Init !!!"); return; } if (mBufferOut != null && !mBufferOut.checkError()) { mBufferOut.println(message); mBufferOut.flush(); } } public void stopClient() { mRun = false; //////////////////////mRun must be false/////////////////////////// if (mBufferOut != null) { mBufferOut.flush(); mBufferOut.close(); } mMessageListener = null; mBufferIn = null; mBufferOut = null; mServerMessage = null; } public void run() { try { // Creates a stream socket and connects it to the specified port number at the specified IP address socket = new Socket(InetAddress.getByName(SERVER_IP), SERVER_PORT); try { // sends the message to the server mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); // receives the message which the server sends back mBufferIn = new BufferedReader(new InputStreamReader(socket.getInputStream())); mRun = true; while (mRun) { // in this while the client listens for the messages sent by the server mServerMessage = mBufferIn.readLine(); if (mServerMessage != null && mMessageListener != null) { mMessageListener.messageReceived(mServerMessage); // call the method messageReceived from MyActivity class } } } catch (Exception e) {} finally { // the socket must be closed. // It is not possible to reconnect to this socket, after it is closed, // which means a new socket instance has to be created. socket.close(); } } catch (Exception e) {} } public interface OnMessageReceived { public void messageReceived(String message) throws IOException; } public boolean isConnected() { if (socket == null) return false; if (socket.isConnected()) return true; else return false; } } 通过引用修改$list
  2. 忽略在&$v中找不到匹配关键字的迭代。
  3. $dataArray中的每个合格值强制转换为数组,并覆盖初始的空子数组。 如果合格值不是数组,它将成为生成的子数组中的唯一元素;如果是的话,那么关于子数组的任何事情都不会改变。

代码:(Demo

$dataArray

输出:

$list = [
    'fruit' => [],
    'animals' => [],
    'objects' => []
];

$dataArray = [
    'fruit' => 'apple',
    'animals' => ['dog', 'cat'],
    'asd' => 'bla'
];

foreach ($list as $k => &$v) {
    if (isset($dataArray[$k])) {
        $v = (array)$dataArray[$k];
    }
}

var_export($list);

答案 3 :(得分:0)

这是两行的解决方案(但您只需将其设置为一行:))

$list = [
    'fruit' => [],
    'animals' => [],
    'objects' => [],
];

$dataArray = [
    'fruit' => 'apple',
    'animals' => ['dog', 'cat'],
    'asd' => 'bla'
];   

$list = array_merge($list, array_intersect_key($dataArray, $list));
array_walk($list, function(&$item){$item = (array)$item;});