Python разбивает массив на подмассивы эквивалентного ранга
Редакция:
У меня есть массив из n отсортированных значений.
Я хочу создать m подмассивов так, чтобы мой лучший элемент попадал в мой первый подмассив, мой второй элемент входил в мой второй подмассив и т. Д., А мой n+1-й лучший элемент помещался в мой первый под массив.
Если у меня есть только два массива, это легко, но если мне нужно больше двух подмассивов, я не знаю, как это сделать.
например, если у меня есть начальный массив:
a = [50, 45, 40, 35, 30, 25, 20, 10, 9, 8]
И я хочу получить 3 подмассива:
x1: [50, 35, 20, 8]
x2: [45, 30, 10]
x3: [40, 25, 9]
Какой самый эффективный / питонный способ сделать это?
5 ответов
ДЛЯ Х СУБЛИСТОВ:
Одна возможность будет сделать:
def get_sublists(original_list, number_of_sub_list_wanted):
sublists = list()
for sub_list_count in range(number_of_sub_list_wanted):
sublists.append(original_list[sub_list_count::number_of_sub_list_wanted])
return sublists
Затем вы можете распаковать вложенные списки, хранящиеся в sublist
,
Например:
a = [5,4,3,2,1,0]
x1, x2 = get_sublists(a, 2)
предоставит вам ожидаемый результат.
Это тривиальное решение. Их, вероятно, что-то более питоническое в itertools или другой библиотеке.
Если вы не понимаете, как работает этот код, взгляните на документацию среза.
Для 2 массивов
x1, x2 = map(list, zip(*zip(*[iter(a)] * 2)))
print(x1, x2, sep='\n')
[5, 3, 1]
[4, 2, 0]
Для 3 массивов
x1, x2, x3 = map(list, zip(*zip(*[iter(a)] * 3)))
print(x1, x2, x3, sep='\n')
[5, 2]
[4, 1]
[3, 0]
Почему это работает
iter(a)
создает итератор в спискеa
, Когда вы выполняете итерацию, элементы израсходованы, и в итоге итератор истощается.[iter(a)] * 2
создает список, который выглядит следующим образомi = iter(a); [i, i]
, Обратите внимание, что один и тот же итератор появляется дважды. Это означает, что когда я беру элемент из первогоi
Я тоже со второгоi
потому что они указывают на один и тот же итератор.- Так! когда я использую
zip
в распакованном списке того же итератораzip(*[iter(a)] * 2)
Когда я объединяю вещи в пару, я извлекаю из одного и того же итератора и, следовательно, естественно исчерпываю их в том порядке, в котором мы хотим. - Я тогда использую другой
zip
транспонировать результаты, а затемmap
сlist
составить их списки вместо кортежей.
Ниже дадим желаемый ответ,
a = [5, 4, 3 ,2, 1, 0]
a.sort(reverse=True)
x1 = []
x2 = []
for i in range(len(a)):
x1.append(a[i]) if (i%2==0) else x2.append(a[i])
print x1, x2
a = [5, 4, 3 ,2, 1, 0]
def get_original_val(original, x):
return [original[index] for index in x]
def get_index(a):
index_x1, index_x2 = [], []
local_list = a if not len(a) % 2 else a + [0]
for idx, x in enumerate(local_list):
target = index_x2 if idx % 2 else index_x1
target.append(idx)
get_x1 = get_original_val(a, index_x1)
get_x2 = get_original_val(a, index_x2)
return get_x1, get_x2
>>>x1, x2 = get_index(a)
>>>x1
[5, 3, 1]
>>>x2
[4, 2, 0]
Вот мое решение проблемы. Он делит список размера l на n частей, где n-1 частей имеют равный размер l/n , а последний n имеет размер l/n + по модулю деления .
def get_sublists(original_list, sublists_number):
list_size = len(original_list)
sublist_size_except_last = list_size//sublists_number
last_sublist_size = list_size%sublists_number
sublists = list()
l_index = 0
r_index = list_size-1
for i in range(sublists_number):
l_index = (i*sublist_size_except_last)
r_index = ((i+1)*sublist_size_except_last)-1
if i != sublists_number-1:
sublists.append(text_list[l_index:r_index])
print(l_index,r_index)
else:
r_index = r_index+last_sublist_size
print(l_index,r_index)
sublists.append(text_list[l_index:r_index])
return sublists
Для списка строк размером 6538434. Мы получаем 5 подсписков внутри одного списка, нарезанного следующим образом:
original_list[0:1307685]
original_list[1307686:2615371]
original_list[2615372:3923057]
original_list[3923058:5230743]
original_list[5230744:6538433]