Случайным образом выбрать элементы списков, содержащих кортежи? - PullRequest
0 голосов
/ 05 января 2020

У меня есть список, содержащий отдельные элементы и кортежи «подпунктов», как показано ниже:

items = ['item_1', 'item_2', 'item_3', 'item_4', ('item_5a', 'item_5b'), 'item_6', ('item_7a', 'item_7b')]

Теперь я хочу выбрать n (здесь 4) количество элементов из указанного списка, например, используя np.random.choice:

>>> np.random.choice(items, 4, replace=False)
array([('item_5a', 'item_5b'), 'item_6', ('item_7a', 'item_7b'), 'item_4'],
      dtype=object)

Это работает, но рассматривает кортежи как один элемент. То, что я ищу, это:

  • Сохраняйте элементы в сгруппированном кортеже - всегда выбирайте вместе
  • Выберите n элементов, включая "подэлементы" в кортеже

Примерно так:

>>> choose_n_items(items, 4, replace=False)
array([('item_5a', 'item_5b'), 'item_6', 'item_4'],
      dtype=object)

Есть ли встроенная функция с этой функциональностью.

Ответы [ 2 ]

1 голос
/ 05 января 2020

Как мне известно, встроенного решения не существует.

Вы можете сделать что-то вроде этого:

По сути, вы считаете tupel числом элементов, которое в нем содержится, и только добавляете их, если есть достаточно места.

import random
random.seed(1) # In case you want to control the output

items = ['item_1', 'item_2', 'item_3', 'item_4', ('item_5a', 'item_5b'), 'item_6', ('item_7a', 'item_7b')]

def random_choice(original_choice_list,n,replace=True):
    list_length = sum(map(lambda x: len(x) if isinstance(x,tuple) else 1,original_choice_list))
    choice_list = original_choice_list.copy()
    output = []
    actual_n = 0
    if not replace and n > list_length:
        raise ValueError("List has only {} elements but you want {}. With replace = False not possible".format(list_length,n))
    while actual_n < n:
        if not choice_list:
            return random_choice(original_choice_list, n, replace)
        item = random.choice(choice_list)
        if isinstance(item,tuple):
            if len(item) + actual_n <= n:
                output.append(item)
                actual_n += len(item)
        else:
            output.append(item)
            actual_n += 1
        if not replace:
            choice_list.remove(item)
    return output
for i in range(5):
    print(random_choice(items,4,replace=False))

print("######")

for i in range(5):
    print(random_choice(items,4,replace=True))

Выход

['item_2', 'item_6', 'item_1', 'item_3']
['item_4', ('item_5a', 'item_5b'), 'item_6']
['item_6', 'item_4', 'item_2', 'item_1']
['item_4', 'item_1', 'item_6', 'item_2']
['item_6', 'item_4', 'item_3', 'item_2']
#####
[('item_5a', 'item_5b'), 'item_1', 'item_3']
['item_1', 'item_1', 'item_1', 'item_6']
[('item_5a', 'item_5b'), 'item_1', 'item_4']
['item_6', 'item_2', 'item_4', 'item_6']
['item_1', ('item_5a', 'item_5b'), 'item_2']
0 голосов
/ 05 января 2020
import numpy as np

items = ['item_1', 'item_2', 'item_3', 'item_4', ('item_5a', 'item_5b'), 'item_6', ('item_7a', 'item_7b')]
output= []
n=4
counter = 0
while counter <4:
    for index, i in enumerate(np.random.randint(0, len(items),n)): 
        tuple_count=0 
        if counter >=4:
            break
        if items[i].__class__==tuple:
            print("in tuple")                
            if (index in range(0,n-2)) and tuple_count<=2:                    
                counter +=len(items[i])
                tuple_count +=1
                output.append(items[i])               

        else:
            counter +=1
            output.append(items[i])

print(output)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...