генерируя все комбинации группировок из списка, который содержит все элементы данного списка [duplicate]

Вы можете использовать эту пользовательскую библиотеку (написанную с помощью Promise) для выполнения удаленного вызова.

function $http(apiConfig) {
    return new Promise(function (resolve, reject) {
        var client = new XMLHttpRequest();
        client.open(apiConfig.method, apiConfig.url);
        client.send();
        client.onload = function () {
            if (this.status >= 200 && this.status < 300) {
                // Performs the function "resolve" when this.status is equal to 2xx.
                // Your logic here.
                resolve(this.response);
            }
            else {
                // Performs the function "reject" when this.status is different than 2xx.
                reject(this.statusText);
            }
        };
        client.onerror = function () {
            reject(this.statusText);
        };
    });
}

Пример простого использования:

$http({
    method: 'get',
    url: 'google.com'
}).then(function(response) {
    console.log(response);
}, function(error) {
    console.log(error)
});
24
задан alexis 8 May 2015 в 23:28
поделиться

2 ответа

Поскольку этот приятный вопрос был возвращен к жизни, вот свежий ответ.

Проблема рекурсивно решается: если у вас уже есть раздел n-1 элементов , как вы используете его для разделения элементов n ? Либо поместите элемент n в один из существующих подмножеств, либо добавьте его как новое одноэлементное подмножество. Это все, что нужно; itertools:

def partition(collection):
    if len(collection) == 1:
        yield [ collection ]
        return

    first = collection[0]
    for smaller in partition(collection[1:]):
        # insert `first` in each of the subpartition's subsets
        for n, subset in enumerate(smaller):
            yield smaller[:n] + [[ first ] + subset]  + smaller[n+1:]
        # put `first` in its own subset 
        yield [ [ first ] ] + smaller


something = list(range(1,5))

for n, p in enumerate(partition(something), 1):
    print(n, sorted(p))

Вывод:

1 [[1, 2, 3, 4]]
2 [[1], [2, 3, 4]]
3 [[1, 2], [3, 4]]
4 [[1, 3, 4], [2]]
5 [[1], [2], [3, 4]]
6 [[1, 2, 3], [4]]
7 [[1, 4], [2, 3]]
8 [[1], [2, 3], [4]]
9 [[1, 3], [2, 4]]
10 [[1, 2, 4], [3]]
11 [[1], [2, 4], [3]]
12 [[1, 2], [3], [4]]
13 [[1, 3], [2], [4]]
14 [[1, 4], [2], [3]]
15 [[1], [2], [3], [4]]
: itertools: itertools: нет itertools, нет наборов, нет повторных выходов и всего только n
33
ответ дан alexis 24 August 2018 в 20:42
поделиться

В отличие от моих комментариев, я не смог быстро найти решение на основе itertools относительно быстро! Изменить: это уже не совсем так, у меня довольно короткое (но медленное и нечитаемое) решение с использованием itertools в значительной степени, см. Конец ответа. Это то, что я получил вместо этого:

Идея состоит в том, что мы находим все комбинации целых чисел, которые складываются до длины списка, а затем получают списки с фрагментами этой длины.

Например, для списка длины 3 комбинации или разбиения являются (3), (2, 1), (1, 2) и (1, 1, 1). Поэтому мы возвращаем первые 3 элемента списка; первые 2, а затем следующий 1; первый 1, затем следующий 2 и первый 1, затем следующий 1, затем следующий 1.

Я получил код для целочисленного partioning из здесь . Однако функции разделов не возвращают все перестановки разделов (т. Е. Для 3 она просто вернет (3), (2, 1) и (1, 1, 1). Поэтому нам нужно вызвать itertools.permutations на каждом из Затем нам нужно удалить дубликаты - так же, как permutations([1, 2, 3]) - [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]], permutations([1, 1, 1]) - [[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]]. Легкий способ удаления дубликатов - это превратить каждый список кортежей в set.

Тогда все, что осталось, - это получение фрагментов списка для длин в кортеже. Например, f([1, 2, 3], [0, 0, 1, 2, 1, 0]) отправляется на [[0], [0, 1], [2, 1, 0]].

Мое определение этого:

def slice_by_lengths(lengths, the_list):
    for length in lengths:
        new = []
        for i in range(length):
            new.append(the_list.pop(0))
        yield new

Теперь мы просто соединим все:

def subgrups(my_list):
    partitions = partition(len(my_list))
    permed = []
    for each_partition in partitions:
        permed.append(set(itertools.permutations(each_partition, len(each_partition))))

    for each_tuple in itertools.chain(*permed):
        yield list(slice_by_lengths(each_tuple, deepcopy(my_list)))

>>> for i in subgrups(my_list):
        print(i)

[[1], [2], [3]]
[[1], [2, 3]]
[[1, 2], [3]]
[[1, 2, 3]]

Также вам нужно сделать import itertools и from copy import deepcopy в верхней части программы.

Изменить: ваш выходной результат не ясен. Я предположил, что вам нужна функция, которую я вам дал, но ваш вывод также содержит [[1,3],[2]], где элементы на выходе находятся в другом порядке, в отличие от остальной части вашего предлагаемого вывода ( Я взял на себя смелость предположить, что вы действительно хотите [[1, 2], [3]] не [[1, 2], 3]).

То есть, я полагаю, что y ou означало, что вывод был следующим:

[[1], [2], [3]]
[[1], [2, 3]]
[[1, 2], [3]]
[[1, 2, 3]]

Если на самом деле это было так:

[[1], [2], [3]]
[[1], [2, 3]]
[[1, 2], [3]]
[[1, 2, 3]]
[[1], [3], [2]]
[[1], [3, 2]]
[[1, 3], [2]]
[[1, 3, 2]]
[[2], [1], [3]]
[[2], [1, 3]]
[[2, 1], [3]]
[[2, 1, 3]]
[[2], [3], [1]]
[[2], [3, 1]]
[[2, 3], [1]]
[[2, 3, 1]]
[[3], [1], [2]]
[[3], [1, 2]]
[[3, 1], [2]]
[[3, 1, 2]]
[[3], [2], [1]]
[[3], [2, 1]]
[[3, 2], [1]]
[[3, 2, 1]]

Тогда вам просто нужно вызвать subgrups для каждого 3- длина перестановки исходного списка, например для каждой перестановки в itertools.permutations(my_list, len(my_list)).

Изменить: теперь, чтобы выполнить мое обещание короткого решения itertools. Предупреждение - оно может быть как нечитаемым, так и медленным.

Сначала мы заменим slice_by_lengths на это:

def sbl(lengths, the_list):
    for index, length in enumerate(lengths):
        total_so_far = sum(lengths[:index])
        yield the_list[total_so_far:total_so_far+length]

Тогда из этот ответ получим наш целочисленная функция секционирования:

def partition(number):
    return {(x,) + y for x in range(1, number) for y in partition(number-x)} | {(number,)}

Эта функция фактически получает все перестановки целочисленных разделов для нас, поэтому нам больше не нужно

for each_partition in partitions:
    permed.append(set(itertools.permutations(each_partition, len(each_partition))))

. Тем не менее, он намного медленнее, чем у нас раньше, поскольку он рекурсивный (и мы реализуем его в Python).

Затем мы просто разделим его:

def subgrups(my_list):
    for each_tuple in partition(len(my_list)):
        yield list(slice_by_lengths(each_tuple, deepcopy(my_list)))

Или менее читаемым, но без определений функций:

def subgrups(my_list):
    for each_tuple in (lambda p, f=lambda n, g:
                          {(x,) + y for x in range(1, n) for y in g(n-x, g)} | {(n,)}:
                              f(p, f))(len(my_list)):
        yield list(my_list[sum(each_tuple[:index]):sum(each_tuple[:index])+length] for index, length in enumerate(each_tuple))

, который является определением функции и двумя строками, настолько близкими к тому, что я изначально указывал (хотя и гораздо менее читаемым и намного медленнее)!

(Функции, называемые subgrups, поскольку первоначально задан вопрос об обнаружении «всех подгрупп»)

10
ответ дан Community 24 August 2018 в 20:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: