2012-07-29 4 views
5

주어진 목록 (또는 numpy로 배열)의 (연속적인) 부분 만 셔플 할 수 있습니까?첫 번째 요소를 수정하고 목록/배열의 나머지 부분을 임의로 섞습니다.

이것이 일반적으로 불가능한 경우 나머지 목록/배열을 섞어 야하는 동안 첫 번째 요소가 고정되는 특별한 경우는 어떨까요?

to_be_shuffled = [None, 'a', 'b', 'c', 'd', ...] 

나머지는 반복적으로 단행 될 것 동안 첫 번째 요소는 항상 유지해야한다 : 예를 들어, 나는 목록/배열을 가지고있다.

하나의 가능한 방법은 전체 목록을 먼저 섞은 다음 첫 번째 요소가 특수 고정 요소 (예 : None)가 아닌지 확인한 다음 특수 요소의 위치와 바꿉니다 (그러면 조회).

더 좋은 방법이 있습니까? 단지

import random 
rest = to_be_shuffled[1:] 
random.shuffle(rest) 
shuffled_lst = [to_be_shuffled[0]] + rest 

답변

5

NumPy와 배열은 슬라이스에 데이터를 복사하지 않습니다

numpy.random.shuffle(a[1:]) 
+0

numpy 배열을 사용하여 구현하기로 선택 했으므로이 방법이 가장 좋은 해결책입니다.다른 솔루션은 또한 매우 유용하며 다른 사람들이 각각의 유스 케이스에 적합하다고 생각하기를 바랍니다. – skyork

9

. 이것을 제자리에서합니다. 즐겨! 트릭을 할해야 start 매개 변수로 1이 함수를 호출하여 목적

from random import randint 

def shuffle(x, start=0, stop=None): 
    if stop is None: 
     stop = len(x) 

    for i in reversed(range(start + 1, stop)): 
     # pick an element in x[start: i+1] with which to exchange x[i] 
     j = randint(start, i) 
     x[i], x[j] = x[j], x[i] 

.

+0

@DavidRobinson을, 감사합니다. 위의 장소에서, 목록/배열의 일부분의 새로운 복사본이 생성되지 않았습니까? – skyork

+2

@kojiro'shuffled_lst'는 그 전에 존재하지 않습니다. 'to_be_shuffled [1 :] = rest' – jamylak

+2

@skyork 아니요,'shuffled_lst'와'rest'는'to_be_shuffled'에있는 데이터의 복사본 (부분 및 완전)입니다. – kojiro

3

내가 (Lib\random.py에 있음) 표준 라이브러리 random 모듈에서 셔플 기능을 가져다가 startstop에 의해 지정된 목록의 일부를 섞어 수 있도록 약간 수정하지 왜

+0

@ J.F.Sebastian : 내가 그랬어. 감사! –

+1

Python 2.x에서 range 대신 xrange를 사용하십시오. – jfs

4

나는 당신이 요구하는 것보다 약간 더 일반적인 접근 방식을 구현하려고하면 흥미롭고 교육적이라고 생각했습니다. 여기서 잠긴 색인을 제외하고 색인을 원래 목록에 셔플하고 색인 목록을 사용하여 체리 목록에서 요소를 선택합니다. 이것은 적절한 솔루션이 아니지만 생성기로 구현되므로 느슨하게 요소를 선택할 수 있습니다.

개선 할 수 있으면 언제든지 편집 해주십시오.

import random 

def partial_shuf(input_list, fixed_indices): 
    """Given an input_list, yield elements from that list in random order 
    except where elements indices are in fixed_indices.""" 
    fixed_indices = sorted(set(i for i in fixed_indices if i < len(input_list))) 
    i = 0 
    for fixed in fixed_indices: 
     aslice = range(i, fixed) 
     i = 1 + fixed 
     random.shuffle(aslice) 
     for j in aslice: 
      yield input_list[j] 
     yield input_list[fixed] 
    aslice = range(i, len(input_list)) 
    random.shuffle(aslice) 
    for j in aslice: 
     yield input_list[j] 

print '\n'.join(' '.join((str(i), str(n))) for i, n in enumerate(partial_shuf(range(4, 36), [0, 4, 9, 17, 25, 40]))) 

assert sorted(partial_shuf(range(4, 36), [0, 4, 9, 17, 25, 40])) == range(4, 36) 
관련 문제