合并PHP数组

5

我有多个关联数组,如果除了 startdate 以外的所有值都相同,我想要将它们合并。如果两个数组确实相同,我想要合并它们并创建一个新元素 enddate,以便显示日期范围的 startdateenddate。范围内的所有日期必须在原始数组中表示,即如果缺少日期,则其两侧的日期不得合并。

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

should become:

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

为了检查另一个数组是否具有相同的值。我正在尝试使用这些数组来重构原始结构中的数组。

5个回答

1
避免使用日期/时间函数,这只是浪费 CPU 时间而没有任何好处(来自 Dave 的回答)。 避免使用大型数组函数(adlawson 的回答),同样是浪费时间,只需以聪明的方式排序和处理数组将更快。
但最重要的是,你想做什么,为什么那些数组会这样,是否有 SQL 在其中?
因为如果有的话,比尝试合并格式不正确的数组要简单得多(恕我直言,你所寻求的转换意味着某些地方出了问题..一个开始时间变成结束时间表示试图保留完整的项目历史记录,在 PHP 本身中没有任何地方)。
如果这确实是你需要的东西,我会给你正确的 PHP 代码,但我非常怀疑这是你的应用程序前进的正确方式。

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)之前。


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 答案的更简化和原地版本。


但是和 Dave 一样,你忘记检查数组元素是否不同了 ;) - Tim

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;

我认为这是一个开始……一些不应该设置的“enddate”被设置了,而且有些比“startdate”还要小,但感谢您的开始。我会尝试调整它。 - user774528
这只是一小段快速的代码,但对于你上面给出的三行代码有效。不过应该非常接近 :) - Dave Child
假设初始数组按照开始日期排序? - Mat

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接