3

所以我在数据库中有一个用于交付时间的字段,它具有某种格式(肯定不是我的设计!):这里有几个例子:

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 个下拉菜单(从、到、关闭从、关闭到)的输入转换为该格式。任何一天都可能根本没有关闭时间。至少一天必须指定交货时间(我检查一下)。

我当然得到了第一部分(分号之前) - 这很容易,之后我完全陷入困境。如果有送货的所有日子都有相同的时间,我就不会有问题。但由于每天都可能完全不同,我不知道该怎么做。

所以这是到目前为止的处理块:

$trimmed 是已修剪的 POST 值数组,

$trimmed['1Monday'] 是星期一从,$trimmed['2Monday'] 是星期一到,

$trimmed['3Monday'] 是星期一休息日,$trimmed['4Monday'] 是星期一休息日。

所以 $M_times 变量将有星期一的开/关时间。

$days_del 数组用于稍后创建作为所需格式的第一部分的字符串。

我可以获得指定时间的第一天,然后我可以尝试捕捉任何匹配项,但如果第一个交货日的值与其他日期不同,那么这将没有用,但在那之后有一些匹配的值。我什至不确定我是否需要使用另一个(编号的)天数组,或者我可以只使用带有 MF 键的主要数组来完成它。

<?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 来查找匹配值的想法,但是任何时候我尝试处理它,我都会遇到一堵墙。任何想法都会非常感激。

4

1 回答 1

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);

看到工作

嗯,那很有趣。

于 2012-07-12T20:27:25.047 回答