所以我在db中有一个字段用于传递时间,并且它具有某种格式(不是我的设计肯定!): 以下是几个例子:
M,T,W,TH; MTWTH 9至4关闭12比1
T,W,TH,F; TTHF 9至5关闭12至2,W 9至12
T,W,TH,F; T 10至7结束2至3,WTH 9至6结束1至2,F 8至5结束1至2
所以基本上,你有一个天数列表,用逗号分隔,然后是分号。 在分号后,有一个天数列表,没有分开,然后是交货时间,包括休息时间。 问题是,每天的交货时间可能不同,所有日子都相同,或者说周一和周二相同,周三不同,周四和周五相同(但周四和周五交货时间不同于周一和周一)星期二)。 如果交货时间与某些天相匹配,那么这些日子应该组合在一起,交货时间列在小组日之后,然后列出其他匹配或单日。指定交货时间的第一天必须先行。
我知道,格式是荒谬的,交付日期/时间应该在按组织ID链接的单独表中,但它是他们现在用于某些下载文件的格式。 我希望稍后改变它,但现在...... 我无法弄清楚如何将输入从4个下拉列表(From,To,Closed From,Closed To)转换为该格式。 任何一天都可能没有关闭时间。至少有一天必须指定交货时间(我检查一下)。
我当然得到了第一部分(在分号前) - 这很容易,之后我完全陷入困境。 如果交货的所有日子都有相同的时间,我就不会有问题。但由于它每天都可能完全不同,我不知道该怎么做。
所以到目前为止这是处理块:
$ trimmed是已修剪的POST值数组,
$ trimmed ['1Monday']是星期一从,$ trimmed ['2Monday']是星期一到,
$ trimmed ['3Monday']是周一关闭的,$ trimmed ['4Monday']是周一关闭。
因此$ M_times变量将具有周一的开/关时间。
$ days_del数组用于稍后创建一个字符串,该字符串是所需格式的第一部分。
我可以在指定的某些时间获得第一天,之后我可以尝试捕获任何匹配,但如果第一个交付日与其他日期的值不同,那么这是没有用的,但之后会有一些匹配的值。我甚至不确定我是否需要使用ano((编号)天数组,或者我只能使用带有M-F键的主数据。
<?php
$days = array('M' => 'Monday', 'T' => 'Tuesday', 'W' => 'Wednesday', 'TH' => 'Thursday', 'F' => 'Friday');
$days_numbered = array(1 => 'M', 'T', 'W', 'TH', 'F');
$days_del = $matches = $full_list = array();
$days_delivery2 = '';
$count_no_del = 0; # initialize count for days with no delivery
$times_6 = '';
foreach ($days as $k => $v){ ##### Beginning of days loop
if (isset($trimmed["1$v"]) && isset($trimmed["2$v"])){ # If both closing and opening times have been specified
$days_del[] = $k;
${$k.'_times'} = $trimmed["1$v"] . ' TO ' . $trimmed["2$v"];
if ((!isset($trimmed["3$v"]) && isset($trimmed["4$v"])) || (isset($trimmed["3$v"]) && !isset($trimmed["4$v"]))){ # If only beginning or only end of lunch(?) break has been specified
$errors[] = 'Delivery times for $v - please specify both start and end of closing time.';
}elseif (isset($trimmed["3$v"]) && isset($trimmed["4$v"]){ # If both beginning and end of lunch(?) breakh have been specified
${$k.'_times'} .= 'CLOSED' . $trimmed["3$v"] . ' TO ' . $trimmed["4$v"];
}
}elseif ((!isset($trimmed["1$v"]) && isset($trimmed["2$v"])) || (isset($trimmed["1$v"]) && !isset($trimmed["2$v"]))){ # If only closing or only opening time has been specified
$errors[] = 'Delivery times for $v - please specify both start and end of delivery time.';
${$k.'_times'} = NULL;
}elseif (!isset($trimmed["1$v"]) && !isset($trimmed["2$v"])){ # No delivery times specified for this day
${$k.'_times'} = NULL;
$count_no_del++;
}
$full_list["$k"] = ${$k.'_times'};
} ##### End of days loop
if ($count_no_del > 0){ # If there are no delivery days specified
$errors[] = 'You must specify delivery hours for at least one day of the week.';
}
$days_delivery1 = implode(',', $days_del);
$days_delivery1 = $days_delivery1 . ' ; ';
foreach ($days_numbered as $num => $val){ # Getting first day for which delivery hours have been specified
if (isset(${$val.'_times'}) && (${$val.'_times'} != NULL)){
${'times_'.$num} = ${$val.'_times'};
$first_day = $num;
break;
}
}
$check_array = array_keys($full_list, ${'times_'.$first_day})); # checking how many other days match the delivery hours for the first specified day.
foreach ($check_array as $array_key){
$days_delivery2 .= $array_key;
}
$days_delivery2 .= " " . ${'times_'.$first_day};
$note_line = $days_delivery1 . " " ; # second part, something like 'MTH 9 To 5, TW 10 TO 5 CLOSED 1 TO 2, F 10 TO 2' should go a s the second part of the string.
?>
正如你所看到的,在以该格式获取字符串的第一部分($ days_delivery1)后,我陷入困境,不知道我到底在做什么。我有一个想法,即使用2个不同的数组(主要的一个和编号的数组)并使用array_keys来查找匹配的值,但是每当我尝试使用它时,我就会碰到一堵墙。任何想法都会被贬低。
答案 0 :(得分:3)
这里可能很困难的事情是将第二部分的条目分组。为了克服这个问题,我建议你将时间转换为4位数表示来规范化它们并连接模式,因此为每个模式创建一个“签名”。
在下面的示例中,我将讨论以下$_POST
数组将导致相应结果字符串的主体:
$_POST1 = array(
'1Monday' => 9,
'2Monday' => 5,
'3Monday' => 12,
'4Monday' => 1,
'1Tuesday' => 9,
'2Tuesday' => 5,
'3Tuesday' => 12,
'4Tuesday' => 1,
'1Wednesday' => 9,
'2Wednesday' => 5,
'3Wednesday' => 12,
'4Wednesday' => 1,
'1Thursday' => 9,
'2Thursday' => 5,
'3Thursday' => 12,
'4Thursday' => 1,
'1Friday' => 9,
'2Friday' => 4,
'3Friday' => 11,
'4Friday' => 12
);
$result1 = "M, T, W, TH, F ; MTWTH 9 TO 5 CLOSED 12 TO 1, F 9 TO 4 CLOSED 11 TO 12";
$_POST2 = array(
'1Monday' => '',
'2Monday' => '',
'3Monday' => '',
'4Monday' => '',
'1Tuesday' => 9,
'2Tuesday' => 5,
'3Tuesday' => 12,
'4Tuesday' => 1,
'1Wednesday' => 9,
'2Wednesday' => 5,
'3Wednesday' => 12,
'4Wednesday' => 1,
'1Thursday' => 9,
'2Thursday' => 5,
'3Thursday' => 12,
'4Thursday' => 1,
'1Friday' => 9,
'2Friday' => 5,
'3Friday' => 12,
'4Friday' => 1
);
$result2 = "T, W, TH, F ; TWTHF 9 TO 5 CLOSED 12 TO 1";
现在让我们来看看我们如何处理这些数据。我将假设我们正在直接使用未处理的POST数组。
<?php
// Obviously we will need this map if the inputs use the full day names
$days = array('M' => 'Monday', 'T' => 'Tuesday', 'W' => 'Wednesday', 'TH' => 'Thursday', 'F' => 'Friday');
// A couple of arrays to hold the results of the loop iterations
$resultDays = $resultTimes = array();
// First we iterate over the days
foreach ($days as $dayCode => $dayFull) {
// Data about this day
$dayData = array(
'open' => 0,
'close' => 0,
'lunchClose' => 0,
'lunchOpen' => 0,
'days' => array()
);
// First get the open/close times
$open = $_POST["1$dayFull"];
$close = $_POST["2$dayFull"];
if (empty($open) || empty($close)) {
// If we don't have both open/close times, skip this day
continue;
}
// We definitely open on this day
$resultDays[] = $dayCode;
$dayData['open'] = $open;
$dayData['close'] = $close;
// Pad the strings to make the signature
$openPadded = str_pad($open, 2, "0", STR_PAD_LEFT);
$closePadded = str_pad($close, 2, "0", STR_PAD_LEFT);
// Now look at lunch times
$lunchClose = $_POST["3$dayFull"];
$lunchOpen = $_POST["4$dayFull"];
if (!empty($lunchClose) || !empty($lunchOpen)) {
// If we have both open/close times, add a lunch break
// Add data to $dayData
$dayData['lunchClose'] = $lunchClose;
$dayData['lunchOpen'] = $lunchOpen;
// Pad the strings to make the signature
$lunchClosePadded = str_pad($lunchClose, 2, "0", STR_PAD_LEFT);
$lunchOpenPadded = str_pad($lunchOpen, 2, "0", STR_PAD_LEFT);
} else {
// So we don't break this signature
$lunchClosePadded = $lunchOpenPadded = '';
}
// Build the signature
$signature = $openPadded.$closePadded.$lunchClosePadded.$lunchOpenPadded;
// Add day data to result times array
if (!isset($resultTimes[$signature])) {
$resultTimes[$signature] = $dayData;
}
$resultTimes[$signature]['days'][] = $dayCode;
}
// Now we can build the string
// Like you say, first part is easy
$firstPart = implode(', ', $resultDays);
// Loop $resultTimes and construct to more sensible arrangements
$secondPart = array();
foreach ($resultTimes as $block) {
$str = implode('', $block['days'])." {$block['open']} TO {$block['close']}";
if (!empty($block['lunchClose']) && !empty($block['lunchOpen'])) {
$str .= " CLOSED {$block['lunchClose']} TO {$block['lunchOpen']}";
}
$secondPart[] = $str;
}
// Now we can construct the final string
$finalResult = $firstPart." ; ".implode(', ', $secondPart);
嗯,这很有趣。