对数组进行排序以避免重复连续值

时间:2015-01-11 05:06:56

标签: php arrays sorting

我有以下数组

$categories = array("first",
"first",
"first",
"first",
"second",
"second",
"second",
"second",
"second",
"third",
"third",
"third",
"third",
"third",
"third",
"third",
"third",
"four",
"four",
"four",
"five",
"five",
"five",
"six",
"six",
"seven");

我想要做的是对数组进行排序,以便同一类别不会一个接一个地出现。即数组应该像

一样排序
array("first","second","third","four","five","six","seven","first","second","third"........)

我知道这可以通过PHP的uasort()函数来实现。但我在思考做比较功能时遇到了麻烦。

我可以做的另一种方法是将每个类别分块到单独的数组中并循环遍历每个数组以创建结果数组,但我不确定它是否有效。

任何提示都将受到高度赞赏。提前致谢

2 个答案:

答案 0 :(得分:2)

以下应该做你想做的事:

$buckets = array_count_values($categories);

$results = array();

while (array_sum($buckets) > 0) {
    foreach ($buckets as $index => $value) {
        if ($value > 0) {
            $results[] = $index;
            $buckets[$index] = $value - 1;
        }
    }
}

print_r($results);

它将数组分解为唯一值及其各自的频率,然后迭代每个值并将它们推送到最终数组,直到消耗掉所有值。

结果

Array
(
    [0] => first
    [1] => second
    [2] => third
    [3] => four
    [4] => five
    [5] => six
    [6] => seven
    [7] => first
    [8] => second
    [9] => third
    [10] => four
    [11] => five
    [12] => six
    [13] => first
    [14] => second
    [15] => third
    [16] => four
    [17] => five
    [18] => first
    [19] => second
    [20] => third
    [21] => second
    [22] => third
    [23] => third
    [24] => third
    [25] => third
)

然后,需要将尾随值重新插入到最终结果中,以便没有重复...读者的练习:)

答案 1 :(得分:0)

如果有人还在寻找这个,我已经创建了这个算法的工作原型。

流程图如下:

random sort without consecutive repeats

Python 实现:

import random

def randomize_list(input_list):
    randomized_list = input_list.copy()
    random.shuffle(randomized_list)
    return randomized_list


def get_repeated_items(input_list, type_key):
    repeated_items = []
    pre_sorted_list = []
    last_item = {}
    for item in input_list:
        if last_item and item[type_key] == last_item[type_key]:
            repeated_items.append(item)
            continue
        pre_sorted_list.append(item)
        last_item = item
    return repeated_items, pre_sorted_list

def recycle_repeated_items(repeated_items, pre_sorted_list, type_key):
    sorted_list = []
    last_item = {}
    changed = False
    for item in pre_sorted_list:
        filtered_types = [item[type_key]] + ([last_item[type_key]] if last_item else [])
        eligible_repeated_item = next(filter(lambda t: t[type_key] not in filtered_types, repeated_items), None)
        if eligible_repeated_item:
            changed = True
            repeated_items.remove(eligible_repeated_item)
            sorted_list.append(eligible_repeated_item)
        sorted_list.append(item)
        last_item = item
    return repeated_items, sorted_list, changed

def randomized_non_repeating_sort(input_list, type_key):
    randomized_list = randomize_list(input_list)
    repeated_items, sorted_list = get_repeated_items(randomized_list, type_key)
    repeated_items, sorted_list, changed = recycle_repeated_items(repeated_items, sorted_list, type_key)
    while repeated_items and changed:
        repeated_items, sorted_list, changed = recycle_repeated_items(repeated_items, sorted_list, type_key)
    return sorted_list + repeated_items

示例用法:

original_list = [
    {'id': 10, 'type': 'A'},
    {'id': 11, 'type': 'A'},
    {'id': 12, 'type': 'A'},
    {'id': 13, 'type': 'A'},
    {'id': 14, 'type': 'B'},
    {'id': 15, 'type': 'B'},
    {'id': 16, 'type': 'B'},
    {'id': 17, 'type': 'C'},
    {'id': 18, 'type': 'C'},
    {'id': 19, 'type': 'D'}
]

print('Original list:')
print(original_list)

print('Randomized non-repeating list (1 of 1,000,000 tests):')

for _ in range(1,1000000):
    output_list = randomized_non_repeating_sort(original_list, 'type')
    repeated_items = get_repeated_items(output_list, 'type')[0]
    if repeated_items:
        raise Exception('CONSECUTIVE REPEATED ITEM FOUND!')
    if len(output_list) != len(original_list):
        raise Exception('LIST LENGTH MISMATCH!')

print(output_list)

"""
Output:
[{'id': 15, 'type': 'B'},
 {'id': 10, 'type': 'A'},
 {'id': 17, 'type': 'C'},
 {'id': 12, 'type': 'A'},
 {'id': 19, 'type': 'D'},
 {'id': 13, 'type': 'A'},
 {'id': 18, 'type': 'C'},
 {'id': 16, 'type': 'B'},
 {'id': 11, 'type': 'A'},
 {'id': 14, 'type': 'B'}]
"""

我还写了一篇博文,详细介绍了这个算法:https://tomaraei.com/random-sort-algorithm-without-consecutive-repeats/