Array Filtering with multiple key-value lookups in PHP
I'm using a wordpress plugin for advanced form design/logic/processing, an开发者_如何转开发d one of it's (biggest) downsides is the awkward way it provides form data. Data is given in an array with two or three items for each field.
if it's a hidden field:
$$$n => id
- where n is the field's order in the form, and NAME is the name/id.id => value
- where id is the name/id and value is the value.
If it's a visible field:
$$$n => LABEL
- where n is the field's order in the form, and LABEL is the human-readable label.$$$id => LABEL
- where id is the name/id of the fieldLABEL => value
- where value is what I actually want.
I'm trying to write a function that will consume this horrid array and return a simpler one with a single id => value
pair for each field.
For example, it will take this (order of fields can't be guaranteed):
array(
'$$$1' => 'command',
'command' => 'signup',
'$$$2' => 'First Name',
'$$$firstname' => 'First Name',
'First Name' => 'John',
'$$$3' => 'Email Address',
'$$$email' => 'Email Address',
'Email Address' => 'john@example.com'
);
And return:
array(
'command' => 'signup',
'email' => 'john@example.com',
'firstname' => 'John'
);
This code works, but feels very awkward. Can you help refine it? Thanks! (My strategy is to ignore everything but the $$$n
fields since they're identical for all forms and there's no simple way to tell if a given field is hidden or not.)
function get_cforms_data($cformsdata) {
$data = array();
foreach ($cformsdata as $key => $value) {
if (strpos($key, '$$$') === 0) {
$newkey = substr($key, 3);
if (is_numeric($newkey)) {
$keys = array_keys($cformsdata, $value);
if (count($keys) == 1) {
// must be a hidden field - NAME only appears once
$data[$value] = $cformsdata[$value];
} else {
// non-hidden field. Isolate id.
foreach($keys as $k) {
if ($k == $key) {
// $$$n - ignore it
continue;
} else {
// $$$id
$k = substr($k, 3);
$data[$k] = $cformsdata[$value];
}
}
}
}
}
}
return $data;
}
Here's a working version:
$i=0;
$result = array();
while (array_key_exists('$$$' . ++$i, $arr)) {
$key = $arr['$$$' . $i];
$result[$key] = $arr[$key];
}
It will print:
Array
(
[command] => signup
[First Name] => John
[Email Address] => john@example.com
)
Here's another version. It is much uglier but does exactly what you want (as I interpreted it)
function get_cforms_data($cformsdata) {
$i=0;
$result = array();
$flipped = array_flip($arr);
while (array_key_exists('$$$' . ++$i, $arr)) {
$key = $arr['$$$' . $i];
$realKey = (!preg_match('~^\${3}\d+$~', $flipped[$key])) ?
substr($flipped[$key], 3) : $key;
$result[$realKey] = $arr[$key];
}
return $result;
}
Returns:
Array
(
[command] => signup
[firstname] => John
[email] => john@example.com
)
See it working: http://ideone.com/5mkbx
Here's what I'd probably do, though I don't think it's that much cleaner than yours or NullUserException's:
function get_cforms_data($cforms_data) {
$ret = array();
$label_to_id = array();
$label_or_id_to_value = array();
foreach ($cforms_data as $key => $value) {
if (substr($key, 0, 3) === "$$$") {
if (!is_numeric($id = substr($key, 3))) {
$label_to_id[$value] = $id;
}
} else {
$label_or_id_to_value[$key] = $value;
}
}
foreach ($label_or_id_to_value as $key => $value) {
$ret[isset($label_to_id[$key]) ? $label_to_id[$key] : $key] = $value;
}
return $ret;
}
精彩评论