Просто array_walk () может вам помочь. Пример:
array_walk($arr, function (&$item) {
if(isset($item[1]['OLD'], $item[1]['NEW'])) unset($item[1]['OLD']);
});
import string
import itertools
chars = string.digits + string.letters
MAX_CHARS = 4
for nletters in range(MAX_CHARS):
for word in itertools.product(chars, repeat=nletters + 1):
print (''.join(word))
Это распечатает все 15018570
слова Вы ищете. Если Вы хотите больше/меньше слова, просто изменяются MAX_CHARS
переменная. Это будет все еще иметь всего два for
s для любого количества символов, и Вы не должны повторять себя. И довольно читаемо..
Я собираюсь отправить свой ответ как самое читаемое и наименее масштабируемое :)
import string
chars = [''] + list(string.lowercase)
strings = (a+b+c+d for a in chars
for b in chars
for c in chars
for d in chars)
for string in strings:
print string
Править: На самом деле это неправильно, поскольку это произведет дубликаты всех строк длины <4. Удаление пустой строки от chars
массив просто произвел бы строки с 4 символами.
Обычно я удалил бы этот ответ, но мне все еще отчасти нравится он, если необходимо генерировать строки той же длины.
Решения @nosklo и @Triptych приводят к различным результатам:
>>> list(map(''.join, itertools.chain.from_iterable(itertools.product("ab",
... repeat=r) for r in range(4)))) # @nosklo's
['', 'a', 'b', 'aa', 'ab', 'ba', 'bb', 'aaa', 'aab', 'aba', 'abb', 'baa', 'bab', 'bba', 'bbb']
>>> ab = ['']+list("ab")
>>> list(map(''.join, (a+b+c for a in ab for b in ab for c in ab)))
['', 'a', 'b', 'a', 'aa', 'ab', 'b', 'ba', 'bb', 'a', 'aa', 'ab', 'aa', 'aaa', 'aab', 'ab', 'aba', 'abb', 'b', 'ba', 'bb', 'ba', 'baa', 'bab', 'bb', 'bba', 'bbb']
Здесь изменил решение @Triptych, которые производят тот же вывод как один @nosklo:
>>> ab = "ab"
>>> list(map(''.join, itertools.chain([''], ab, (a+b for a in ab for b in ab),
... (a+b+c for a in ab for b in ab for c in ab))))
['', 'a', 'b', 'aa', 'ab', 'ba', 'bb', 'aaa', 'aab', 'aba', 'abb', 'baa', 'bab', 'bba', 'bbb']
Я не думаю, что это - плохая вещь, если Вы понимаете (и документ :-) это. Я не сомневаюсь, что может быть больше pythonic пути или умного решения (с лямбдами или этажеркой), но я всегда одобрял удобочитаемость по уму.
Так как необходимо генерировать все возможности 1-, 2-, 3-и "слова" с 4 символами, этот метод так же хорош как любой. Я не уверен, сколько времени это взяло бы, так как Вы эффективно генерируете (очень примерно) 14 миллионов строк вывода (но вероятно каждое решение имело бы ту проблему).
Предварительное вычисление общих префиксов может обеспечить повышение скорости, но Вы были бы более обеспеченным измерением его, чтобы проверить (всегда проверка, никогда не принимать):
chars = string.digits + string.uppercase + string.lowercase
for a in chars:
print a
for b in chars:
ab = '%s%s' % (a, b)
print ab
for c in chars:
abc = '%s%s' % (ab, c)
print abc
for d in chars:
print '%s%s' % (abc, d)
Править: Я на самом деле сделал некоторые сравнительные тесты (с Python Windows 2.6.1) - эта версия берет приблизительно 2,25 единицы измерения времени по сравнению с оригиналом 2.84, таким образом, это на 26% быстрее. Я думаю, что это могло бы гарантировать его использование (снова, пока оно документируется ясно, чего оно пытается достигнуть).
Запишите для программиста сначала - второй компьютер.
Если это ясно и очевидно понять затем свое корректное.
Если вопросы скорости И компилятор не оптимизируют его так или иначе И если Вы измеряете его, И это - проблема - затем думают о более быстром более умном пути!
Существует много алгоритмов для генерации каждой перестановки набора. Что Вы хотите, вот связанная проблема, но не непосредственно analagous. Предложенное Чтение
Это точно не отвечает на вопрос, но это возвратилось бы n
комбинация th для данной максимальной длины и символов в алфавите для использования:
#!/usr/bin/python
def nth_combination(n, maxlen=4, alphabet='abc'):
"""
>>> print ','.join(nth_combination(n, 1, 'abc') for n in range(3))
a,b,c
>>> print ','.join(nth_combination(n, 2, 'abc') for n in range(12))
a,aa,ab,ac,b,ba,bb,bc,c,ca,cb,cc
>>> import string ; alphabet = string.ascii_letters + string.digits
>>> print ','.join(nth_combination(n, 4, alphabet) for n in range(16))
a,aa,aaa,aaaa,aaab,aaac,aaad,aaae,aaaf,aaag,aaah,aaai,aaaj,aaak,aaal,aaam
>>> print ','.join(nth_combination(n, 4, alphabet)
... for n in range(0, 14000000, 10**6))
a,emiL,iyro,mKz2,qWIF,u8Ri,zk0U,Dxav,HJi9,LVrM,P7Ap,UjJ1,YvSE,2H1h
"""
if maxlen == 1:
return alphabet[n]
offset, next_n = divmod(n, 1 + len(alphabet)**(maxlen-1))
if next_n == 0:
return alphabet[offset]
return alphabet[offset] + nth_combination(next_n-1, maxlen-1, alphabet)
if __name__ == '__main__':
from doctest import testmod
testmod()
Это, конечно, имеет смысл, только если Вам нужен произвольный доступ к набору комбинаций вместо того, чтобы всегда выполнить итерации через них всех.
Если maxlen
высоко, некоторая оптимизация скорости могла быть достигнута, например, путем избавления от конкатенации строк и перевычисления длины alphabet
и maxlen-1
на каждом уровне рекурсии. Нерекурсивный подход мог бы иметь смысл, также.