我一直试图通过这种方式来思考,但是还无法获得一个干净的解决方案。 所以,我有一个列表列表,如..
data = [
[1,2,3],
['a','b'],
['fush', 'bush', 'mish', 'bish']
]
我想从中取样“ k”值。
例如,如果k = 2,则它可以返回类似[2, 'b']
的内容(并将其从考虑范围中删除)。
如果k = 4,则它应返回类似[3, 'a','bush', 1]
的内容。
答案 0 :(得分:2)
怎么样?
import random
from itertools import chain, zip_longest
def special_sample(data, n):
length = len(data)
n_elements, excess = divmod(n, length)
samples = (random.sample(sub, n_elements + 1)
if index < excess
else random.sample(sub, n_elements)
for index, sub in enumerate(data))
return [element for element in chain.from_iterable(zip_longest(*samples)) if element is not None]
special_sample(data, 4)
输出:
[3, 'a', 'bush', 1]
答案 1 :(得分:1)
您可以先使用random.shuffle
来随机整理data
中的每个子列表,压缩并链接子列表,然后使用itertools.islice
来获取前k
个项目:
import random
from itertools import islice, chain
k = 4
for l in data:
random.shuffle(l)
print(list(islice(chain.from_iterable(zip(*data)), k)))
示例输出:
[1, 'a', 'mish', 3]
答案 2 :(得分:1)
您可以尝试一下 注意:我假设您想每次删除列表的第一个元素,可以用随机索引替换它
data = [
[1,2,3],
['a','b'],
['fush', 'bush', 'mish', 'bish']
]
def sampleList(k, data):
sampledList = []
dl = len(data)
for idx in range(0,k):
# assuming here that we sample the first element of list always
d = data[idx % dl] # wrap around the index
sampledList.append(d[0]) # Add sampled value to return list
del d[0] # Delete sampled value from original list
return sampledList
print sampleList(2, data)
print data
print sampleList(4, data)
print data
此输出为
[1, 'a']
[[2, 3], ['b'], ['fush', 'bush', 'mish', 'bish']]
[2, 'b', 'fush', 3]
[[], [], ['bush', 'mish', 'bish']]
希望这会有所帮助。
答案 3 :(得分:0)
您也可以这样做:
import random
def fun(data, k):
output = []
for i in range(k):
if i > len(data):
# if i is greater than len of data then reset i
i = i % len(data)
# select a random element from sublist and remove it.
x = random.choice(data[i])
output.append(x)
data[i].remove(x)
return output
print(fun(data, 3))
输出:
[3, 'b', 'bish']
# data
# [[1, 2], ['a'], ['fush', 'bush', 'mish']]
答案 4 :(得分:0)
再次采用另一种方法。首先,您必须一次flatten your list of lists一次,即
flat_data = [item for sublist in data for item in sublist]
,然后填写另一个列表,直到完成基于k的采样为止。
import random as rd
k = 4
sample = []
while len(sample) < k:
if rd.random() > .5:
rd.shuffle(flat_data) # costly
sample.append(
flat_data.pop(0)
)
# where sample now is, say, ['b', 'bish', 2, 'a']
答案 5 :(得分:0)
如果您使生成器生成随机播放,请吐出随机值,然后再次随机播放,您可以循环遍历这些生成器,以永远以正确的顺序吐出值。每次用完都会重新洗牌:
从itertools导入周期开始,链式
def randGen(l):
while True:
r = random.sample(l, k=len(l))
yield from r
data = [ [1,2,3],['a','b'],['fush', 'bush', 'mish', 'bish']]
gs = map(next, cycle(randGen(l) for l in data)) # setup a generator on the cycle
for i in range(30):
print(next(gs), end = ",")
结果
1,b,bush,3,a,bish,2,b,mish,3,a,fush,1,a,fush,2,b,bish,1,a,mish,3,b,bush,2,a,bish,1,b,mish ...
如果您只想要列表中的某个数字,islice()
使其非常方便:
list(islice(gs, 9))
# [2, 'a', 'mish', 1, 'b', 'bish', 3, 'b', 'fush']
答案 6 :(得分:0)
好吧,这个答案可能太晚了,可能效率不高,但是我还是决定试一试:
import random
data = [
[1, 2, 3],
['a', 'b'],
['fush', 'bush', 'mish', 'bish']
]
k = 5
sample_list = []
def filter_chosen_element(sample_list1, data1):
for i in range(len(data1)):
for j in range(len(sample_list1)):
if sample_list1[j] in data1[i]:
data1[i].remove(sample_list1[j])
if k <= len(data):
for i in range(k):
sample_list.append(random.choice(data[i]))
filter_chosen_element(sample_list, data)
else:
for i in range(k):
sample_list.append(random.choice(data[i % 3]))
filter_chosen_element(sample_list, data)
print(sample_list)
print(data)
答案 7 :(得分:0)
您可以使用列表的索引创建排列,创建一个矩阵,其列为这些索引,然后将矩阵展平,从而按使用顺序为您提供数组的索引。
由于某些列表比其他列表长,因此请根据最短的列表限制索引的长度。
def sample_from_matrix(data, k):
min_size = min([len(i) for i in data])
indexes = np.column_stack ( [ np.random.permutation(min_size) for i in data ] )
indexes = indexes.flatten()
return [ data[i % len(data)][indexes[i]] for i in range(min(k, len(indexes))) ]