如果除startdate
之外的所有值都相同,我想要合并多个关联数组。如果两个数组确实相同,我想合并它们并创建一个新元素enddate
,以便startdate
和enddate
显示日期范围。范围内的所有日期必须以原始数组表示,即如果缺少日期,则不得合并其任何一侧的日期。
Array('color'=>'red','size'=>'large','shape'=>'circle','startdate'=>'2011-08-17')
Array('color'=>'red','size'=>'large','shape'=>'circle','startdate'=>'2011-08-18')
Array('color'=>'red','size'=>'large','shape'=>'square','startdate'=>'2011-08-20')
应该成为:
Array('color'=>'red','size'=>'large','shape'=>'circle','startdate'=>'2011-08-17','enddate'=>'2011-08-18')
Array('color'=>'red','size'=>'large','shape'=>'square','startdate'=>'2011-08-20')
到目前为止,我已经尝试循环遍历每个数组并创建一个多维数组:
foreach($arrays as $id => $array){
$mergearray[$array['red']][$array['large']][$array['circle']] = $id;
};
以检查另一个数组是否具有相同的值。我正在尝试使用这些数组来重建原始结构中的数组。
答案 0 :(得分:1)
避免日期/日期功能浪费cpu时间,没有额外的好处(Dave回答)。 避免使用海量数组函数(来自adlawson的回答),同样浪费时间,只需订购数组并处理智能方式会更快。
但大多数情况下,你想要做什么,为什么那些数组就像那样......那背后有一个SQL吗?
因为如果存在,那么解决方案比尝试合并格式错误的数组要简单得多(尽管如此,你所寻求的转换意味着在某些时候出现了问题...... start_time成为end_time表示尝试保留一个完整的项目历史,在PHP本身没有地位imho)。
如果真的是你需要的话,我会给你正确的PHP代码,但我很怀疑这是你申请的正确方法。
答案 1 :(得分:0)
这样的事情可以解决问题:
$newArray = array();
$newLine = false;
$prev_day = false;
foreach ($array as $line) {
$this_day = strtotime($line['startdate']);
if (($newLine) && ($prev_day == strtotime('-1 day', $this_day))) {
$newLine['enddate'] = $line['startdate'];
$newArray[] = $newLine;
$newLine = false;
} elseif (!$newLine) {
$newLine = $line;
}
if ($newLine) {
$newLine['enddate'] = $line['startdate'];
}
$prev_day = $this_day;
}
$newArray[] = $newLine;
答案 2 :(得分:0)
我看不到这种合并的实际实现,但这应该有效。它可能看起来很长,但它会照顾好一些事情。
/**
* @example array_merge_allbutstartdate($array1, $array2, $array3, $array4, $arr...)
* @param array $array1
* @param array $array2, $arr...
* @return array
*/
function array_merge_allbutstartdate(array $array1, array $array2)
{
$out = array();
$date = array();
$startKey = 'startdate';
$endKey = 'enddate';
foreach (func_get_args() as $item) {
if (!is_array($item)) {
trigger_error('All arguments should be an array.', E_USER_ERROR);
}
$temp = null;
if (isset($item[$startKey])) {
$temp = $item[$startKey];
unset($item[$startKey]);
}
if (!in_array($item, $out)) {
$i = count($out);
$out[] = $item;
} else {
$i = array_search($item, $out);
}
if (null !== $temp) {
$date[$i][] = $temp;
}
}
foreach ($date as $j => $row) {
array_map('strtotime', $row);
$start = array_search(min($row), $row);
$end = array_search(max($row), $row);
// Add start date
$out[$j][$startKey] = $date[$j][$start];
// Only add end date if it is not equal to start date
if ($date[$j][$start] !== $date[$j][$end]) {
$out[$j][$endKey] = $date[$j][$end];
}
}
return $out;
}
答案 3 :(得分:0)
鉴于你已经拥有了一个数组数组,你实际上要做的是删除连续的条目(除了每个时间跨度的第一个条目)。
您的算法将是:
$expected_start_time= 0; // initial val
foreach($all_entries as $k => &$v) {
$start_time = strtotime($v['startdate']);
if($start_time != $expected_start_time) {
$range_start =& $v; // this is a range beginning. Put end date in here
} else {
$range_start['enddate'] = $v['startdate'];
unset($all_entries[$k]);
}
$expected_date = strtotime('+1 day', $start_time);
}
这基本上是Dave Child答案的一个更小的,就地版本。
答案 4 :(得分:0)
function group_and_sort($data)
{
$out = array();
while($data) {
// Shift off the first element
$buffer = array_shift($data);
$end_date = $buffer['startdate'];
// Try to group successive elements...
while($data) {
// Case 1: Does the next element differ by more than just date?
if(count(array_diff_assoc($buffer, $data[0])) > 1) {
break;
}
// Case 2: Does the next element have an unexpected date?
$expected_date = date('Y-m-d', strtotime('+1 day', strtotime($end_date)));
if($data[0]['startdate'] != $expected_date) {
break;
}
// Otherwise, push end_date forward and throw away the element
$end_date = $data[0]['startdate'];
array_shift($data);
}
// If the dates differ, record the range.
if($buffer['startdate'] != $end_date) {
$buffer['enddate'] = $end_date;
}
$out[] = $buffer;
}
return $out;
}
假设元素已按日期排序。如果他们不是,你可以使用:
function sort_startdate($a, $b)
{
return strcmp($a['startdate'], $b['startdate']);
}
usort($data, 'sort_startdate');
将其传递给group_and_sort($data)
。