簡體   English   中英

從未知深度多維創建一個新數組並保持相同的結構

[英]Create a new array from a unknown depth multidimensional and keep the same structure

我有一個可以有任何深度的多維數組。 我想做的是根據動態鍵過濾整個路徑並創建一個新數組。

數組示例

$originalArray = [
    "title" => "BACKPACK MULTICOLOUR",
    "description" => "description here",
    "images" => [
        [
            "id" => 12323123123,
            "width" => 635,
            "height" => 560,
            "src" => "https://example.com",
            "variant_ids": [32694976315473, 32863017926737],
        ],
        [
            "id" => 4365656656565,
            "width" => 635,
            "height" => 560,
            "src" => "https://example.com",
            "variant_ids": [32694976315473, 32863017926737],
        ]
    ],
    "price" => [
        "normal" => 11.00,
        "discount" => [
            "gold_members" => 9.00,
            "silver_members" => 10.00,
            "bronze_members" => null
        ]
    ]
];

示例輸出應該如何與鍵“標題,寬度,高度,gold_members”過濾掉。 只有來自數組樹末尾的鍵應該是有效的,所以當圖像在過濾器中時不會發生任何事情

$newArray = [
    "title" => "BACKPACK MULTICOLOUR",
    "images" => [
        [
            "width" => 635,
            "height" => 560,
        ],
        [
            "width" => 635,
            "height" => 560,
        ]
    ],
    "price" => [
        "discount" => [
            "gold_members" => 9.00,
        ]
    ]
];

我想我應該創建一個循環遍歷每個元素的函數,當它是一個關聯數組時,它應該再次調用自己

因為過濾后的路徑是未知的,所以我無法制作這樣的硬編碼設置器:

$newArray["images"][0]["width"] = 635

以下過濾器將是一個示例,但它基本上應該是動態的

例如我現在擁有的:

$newArray = handleArray($originalArray);
    

handleArray($array) 
{
    $filter = ["title", "width", "height", "gold_members"];

    foreach ($array as $key => $value) {
        if (is_array($value)) {
            $this->handleArray($value);
        } else {
            if (in_array($key, $filter)) {
                // put this full path in the new array
            }
        }
    }
}

[已解決] 更新:

感謝@trincot ,我解決了我的問題

我使用了他的代碼並添加了一個額外的檢查以將具有多個值的數組添加到新數組中

我解決問題的代碼:

<?php
function isListOfValues($array) {            
    $listOfArrays = [];

    foreach ($array as $key => $value) {
        $listOfArrays[] = ! is_array($value) && is_int($key);
    }

    return array_sum($listOfArrays) === count($listOfArrays);
}

function filterKeysRecursive(&$arr, &$keep) {
    $result = [];

    foreach ($arr as $key => $value) {
        if (is_array($value) && ! isListOfValues($value)) {
            $value = filterKeysRecursive($value, $keep);
            
            if (count($value)) {
                $result[$key] = $value;
            }                    
        } else if (array_key_exists($key, $keep)) {
            $result[$key] = $value;
        }
    }
    
    return $result;
}

$keep = array_flip(["title", "width", "height", "gold_members"]);
        
$result = filterKeysRecursive($originalArray, $keep);

我對您的建議是編寫一個自定義函數來將結構從一種模式轉換為另一種模式:

function transform(array $originalArray): array {
    array_walk($originalArray['images'], function (&$a, $k) {
      unset($a['id']); unset($a['src']);
    });
    unset($originalArray['description']);
    unset($originalArray['price']['normal']);
    unset($originalArray['price']['discount']['silver_members']);
    unset($originalArray['price']['discount']['bronze_members']);
    
    return $originalArray;
}
var_dump(transform($originalArray));

如果您熟悉 OOP,我建議您例如查看DTO在 API 平台中的工作原理,並通過創建自定義 DataTransformers 將這個想法注入您的代碼,您可以在其中指定要使用轉換器支持的結構類型和轉換方法一個結構到另一個結構。

您可以使用具有以下邏輯的遞歸函數:

  • 基本情況:與鍵關聯的值不是數組(它是“葉子”)。 在這種情況下,僅當鍵位於所需鍵列表中時,新對象才會具有該鍵/值。

  • 遞歸情況:與鍵關聯的值是一個數組。 對該值應用遞歸。 僅當返回的結果不是空數組時才添加鍵。 在這種情況下,將過濾后的值與結果對象中的鍵相關聯。

為了加快在鍵列表中的查找速度,最好將該列表翻轉為關聯數組。

這是實現:

function filter_keys_recursive(&$arr, &$keep) {
    foreach ($arr as $key => $value) {
        if (is_array($value)) {
            $value = filter_keys_recursive($value, $keep);
            if (count($value)) $result[$key] = $value;
        } else if (array_key_exists($key, $keep)) {
            $result[$key] = $value;
        }
    }
    return $result;
}

$originalArray = ["title" => "BACKPACK MULTICOLOUR","description" => "description here","images" => [["id" => 12323123123,"width" => 635,"height" => 560,"src" => "https://example.com"],["id" => 4365656656565,"width" => 635,"height" => 560,"src" => "https://example.com"]],"price" => ["normal" => 11.00,"discount" => ["gold_members" => 9.00,"silver_members" => 10.00,"bronze_members" => null]]];

$keep = array_flip(["title", "width", "height", "gold_members"]);

$result = filter_keys_recursive($originalArray, $keep);
  • 在每個鍵和子數組上遞歸迭代數組。
  • 如果 foreach 中的當前鍵是結果中的必需鍵,則:
    • 如果值不是數組,只需賦值
    • 如果該值是一個數組,則遞歸地向下迭代該值,以防萬一需要對子數組鍵進行任何其他過濾。
  • 如果 foreach 中的當前鍵不是結果中的必需鍵,則:
    • 如果它本身是一個數組,則遞歸迭代值。 這是必需的,因為可能存在我們需要的深層過濾器鍵之一。 如果結果不是空數組,則獲取結果並僅將其包含在當前子結果中。 否則,我們可以安全地跳過它,因為該行沒有必需的鍵。

片段:

<?php

function filterKeys($array, $filter_keys) {
    $sub_result = [];
    foreach ($array as $key => $value) {
        if(in_array($key, $filter_keys)){// if $key itself is present in $filter_keys
            if(!is_array($value)) $sub_result[$key] = $value;       
            else{
                $temp = filterKeys($value, $filter_keys);
                $sub_result[$key] = count($temp) > 0 ? $temp : $value;
            }
        }else if(is_array($value)){// if $key is not present in $filter_keys - iterate over the remaining subarray for that key
            $temp = filterKeys($value, $filter_keys);
            if(count($temp) > 0) $sub_result[$key] = $temp;
        }
    }
    
    return $sub_result;
}

$result = filterKeys($originalArray, ["title", "width", "height", "gold_members"]);

print_r($result);

在線演示

試試這個方法。

    $expectedKeys = ['title','images','width','height','price','gold_members'];

    function removeUnexpectedKeys ($originalArray,$expectedKeys)
    {
        foreach ($originalArray as $key=>$value) {
          if(is_array($value)) {
            $originalArray[$key] = removeUnexpectedKeys($value,$expectedKeys);
            if(!is_array($originalArray[$key]) or count($originalArray[$key]) == 0) {
                unset($originalArray[$key]);
            }
          } else {
              if (!in_array($key,$expectedKeys)){
                  unset($originalArray[$key]);
              }
          }
        }
        return $originalArray;
    }
    
    $newArray = removeUnexpectedKeys ($originalArray,$expectedKeys);
    print_r($newArray);

在編輯器上檢查這個, https://www.online-ide.com/vFN69waXMf

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM