أفضل طريقة لدمج المصفوفة بشكل متكرر دون كتابة مفاتيح تكرار
-
03-10-2019 - |
سؤال
لدي مجموعة متعددة الأبعاد من بيانات النموذج التي لم يتم تحديدها من YAML. على هذا النحو ، يبدو شيئًا كهذا:
Array(
'name' => 'Somone',
'email' => 'someone@none.local',
'billing' => Array(
'address_1' => '1234 Somewhere'
'address_2' => NULL,
'city' => 'Somewhere',
'state' => 'ST'
'country' => 'CO'
'postal_code' => '12345'
),
'shipping' => Array(
'address_1' => '1234 Somewhere'
'address_2' => NULL,
'city' => 'Somewhere',
'state' => 'ST'
'country' => 'CO'
'postal_code' => '12345'
)
);
ما يجب علي فعله هو تسطيح هذا حتى أتمكن من إخراج بعض CSV ، لذلك يجب أن يبدو مثل هذا:
Array(
'name' => 'Somone',
'email' => 'someone@none.local',
'billing_address_1' => '1234 Somewhere'
'billing_address_2' => NULL,
'billing_city' => 'Somewhere',
'billing_state' => 'ST'
'billing_country' => 'CO'
'billing_postal_code' => '12345'
'shipping_address_1' => '1234 Somewhere'
'shipping_address_2' => NULL,
'shipping_city' => 'Somewhere',
'shipping_state' => 'ST'
'shipping_country' => 'CO'
'shipping_postal_code' => '12345'
);
لن أعرف أبدًا على وجه اليقين مدى عمق المصفوفة/التجزئة - يكون ذلك مستويين فقط كما هو موضح هنا أو يمكن أن يكون 5.
هذا أيضًا في Symfony 1.4 ، لذا فإن SFFORM مع جميع الكماليات المتوفرة إذا لزم الأمر. أعتقد أنه يجب أن تكون هناك طريقة معقولة للقيام بذلك باستخدام مخطط (مخطط) عنصر واجهة المستخدم. ومع ذلك ، أود تجنب ربط البيانات مرة أخرى إلى النموذج إن أمكن. هذا ليس جزءًا من عملية تقديم النموذج الفعلية ، ولكنها منفصلة تمامًا في إجراء للمسؤولين لتنزيل مجموعات البيانات المقدمة.
المحلول
مجرد صخب سريع ولكنه يعمل بشكل جيد:
function array_flatten($array, $prefix = '') {
$newArray = array();
foreach($array as $key => $value) {
if(is_array($value)) {
$newArray = array_merge($newArray, array_flatten($value, $key));
}
else {
$index = empty($prefix) ? $key : $prefix.'_'.$key;
$newArray[$index] = $value;
}
}
return $newArray;
}
اختبار:
$a = array(
"a" => "b",
"ca" => array(
"de" => "ef",
"ef" => "gd"
)
);
var_dump(array_flatten($a));
// Output:
/*
array(3) {
["a"]=>
string(1) "b"
["ca_de"]=>
string(2) "ef"
["ca_ef"]=>
string(2) "gd"
}
*/
نصائح أخرى
function flatten(Array $array, $name = '') {
$ret = array();
foreach ($array as $key => $value) {
$itemname = ($name ? $name . '_' : '') . $key;
if (is_array($value)) {
$ret = array_merge($ret, flatten($value, $itemname));
} else {
$ret[$itemname] = $value;
}
}
return $ret;
}
وماذا عن هذا؟ لم أكن أعرف كيف تريد التعامل مع المفاتيح المكررة ، لذلك تركت هذا الخيار متروك لك. فقط استبدل ; // Do something here on duplicate key
مع الرمز الخاص بك.
$info = Array(
'name' => 'Someone',
'email' => 'someone@none.local',
'billing' => Array(
'address_1' => '1234 Somewhere',
'address_2' => NULL,
'city' => 'Somewhere',
'state' => 'ST',
'country' => 'CO',
'postal_code' => '12345'
),
'shipping' => Array(
'address_1' => '1234 Somewhere',
'address_2' => NULL,
'city' => 'Somewhere',
'state' => 'ST',
'country' => 'CO',
'postal_code' => '12345'
)
);
function explodeArray($array, &$data, $prefix = "") {
foreach ($array as $key => $value) {
if (is_array($value)) {
explodeArray($value, $data, $prefix . $key . "_");
} else {
if (!array_key_exists($prefix . $key, $data)) {
$data[$prefix . $key] = $value;
} else {
; // Do something here on duplicate key
}
}
}
}
$result = array();
explodeArray($info, $result);
print_r($result);