モジュールをインポートせずにリストの要素をシャッフルしたい。シャッフルの種類はリフルシャッフル。いいえを分割したい場所。リストの要素を 2 つに分割し、それらをインターリーブします。
奇数がある場合。要素の場合、後半には余分な要素が含まれている必要があります
例: リスト = [1,2,3,4,5,6,7]
then the final list should look like [1,4,2,5,3,6,7]
モジュールをインポートせずにリストの要素をシャッフルしたい。シャッフルの種類はリフルシャッフル。いいえを分割したい場所。リストの要素を 2 つに分割し、それらをインターリーブします。
奇数がある場合。要素の場合、後半には余分な要素が含まれている必要があります
例: リスト = [1,2,3,4,5,6,7]
then the final list should look like [1,4,2,5,3,6,7]
楽しみのために、再帰的な解決策:
def interleave(lst1, lst2):
if not lst1:
return lst2
elif not lst2:
return lst1
return lst1[0:1] + interleave(lst2, lst1[1:])
Python 2.x では次のように使用します (Python 3.x では、//
代わりに を使用します/
)。
lst = [1,2,3,4,5,6,7]
interleave(lst[:len(lst)/2], lst[len(lst)/2:])
=> [1, 4, 2, 5, 3, 6, 7]
上記は、長さが偶数か奇数かに関係なく、任意の長さのリストで問題なく機能します。
listA = [1,2,3,4,5,6,7,8,9]
listLen = len(listA)/2
listB = listA[:listLen]
listC = listA[listLen:]
listD = []
num = 0
while num < listLen:
if len(listB) >= num:
listD.append(listB[num])
listD.append(listC[num])
num += 1
if len(listA)%2 != 0:
listD.append(listC[num])
print listD
別の回答を見た後、他の人の回答の改訂版である再帰バージョンも追加していますが、単一の引数で関数を呼び出すだけでよいため、呼び出しが簡単です(シャッフルしようとしているリスト) そしてそれは他のすべてを行います:
def interleave(lst):
def interleaveHelper(lst1,lst2):
if not lst1:
return lst2
elif not lst2:
return lst1
return lst1[0:1] + interleaveHelper(lst2, lst1[1:])
return interleaveHelper(lst[:len(lst)/2], lst[len(lst)/2:])
あなたがそれを呼び出すとき、あなたは言うことができますinterleave(list)
例: list = [1,2,3,4,5,6,7] の場合、最終的なリストは [1,4,2,5,3,6,7] のようになります。
これを確実に行う関数を次に示します。
def riffle(deck):
'''
Shuffle a list like a deck of cards.
i.e. given a list, split with second set have the extra if len is odd
and then interleave, second deck's first item after first deck's first item
and so on. Thus:
riffle([1,2,3,4,5,6,7])
returns [1, 4, 2, 5, 3, 6, 7]
'''
cut = len(deck) // 2 # floor division
deck, second_deck = deck[:cut], deck[cut:]
for index, item in enumerate(second_deck):
insert_index = index*2 + 1
deck.insert(insert_index, item)
return deck
そしてそれを単体テストするには...
import unittest
class RiffleTestCase(unittest.TestCase):
def test_riffle(self):
self.assertEqual(riffle(['a','b','c','d','e']), ['a','c','b','d','e'])
self.assertEqual(riffle([1,2,3,4,5,6,7]), [1,4,2,5,3,6,7])
unittest.main()
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
def riffle(deck):
new_deck = []
deck_1 = deck[:len(deck)//2]
deck_2 = deck[len(deck)//2::]
for i in range(len(deck)//2):
new_deck.append(deck_1[i])
new_deck.append(deck_2[i])
if len(deck) % 2 == 1:
new_deck.append(deck[-1])
return new_deck
deck = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
print(riffle(deck))
>>> ll = list(range(1,8))
>>> mid = len(ll)/2 # for Python3, use '//' operator
>>> it1 = iter(ll[:mid])
>>> it2 = iter(ll[mid:])
>>> riff = sum(zip(it1,it2), ()) + tuple(it2)
>>> riff
(1, 4, 2, 5, 3, 6, 7)
これが宿題である場合は、ここでの作業方法sum
とzip
作業、2 番目のパラメーターの目的、最後に追加されるsum
理由tuple(it2)
、およびこのソリューションに固有の非効率性がどのように含まれているかを説明する準備をしてください。
入力リストを 2 つの部分に分割し、zip といくつかのリスト操作を使用して項目をインターリーブすることができます。
n = 9
l = range(1,n+1)
a = l[:n/2]
b = l[n/2:]
c = zip(a,b)
d = list()
for p in c :
d.extend(list(p))
if n%2==1:
d.append(b[n/2])
print(d)
next
Python の反復子の機能を利用することで、これをかなり簡単に行うことができます。
最初に行うことは、要素を 2 つの部分に分割することです。
次に、Python のiter
関数を使用して、これら 2 つの部分を反復子に変換します。この手順は省略できますがnext(iterable)
、手動でリストにインデックスを付けるよりも呼び出しの方がはるかにクリーンであることがわかりました。
最後に、リストの前半をループし、その半分に追加する要素ごとに、後者の対応する要素を追加します (呼び出すとnext
、シーケンスの次の項目が得られます)。
例えば:
elements = [1,2,3,4,5,6,7]
half_point = len(elements)/2
a = iter(elements[0:half_point])
b = iter(elements[half_point: ])
result = []
for i in range(half_point):
result.append(next(a))
result.append(next(b))
if len(elements) % 2 != 0:
result.append(next(b))
print result
>>> [1, 4, 2, 5, 3, 6, 7]
一番下の最後のビットは、リストが奇数かどうかを確認します。そうであれば、最後の要素をリストの最後に追加します。
創造力があれば、圧縮してから解凍することで、おそらくこれをかなり圧縮できますが、それはあなたが探索するときのために残しますitertools
;)