Python 2.7:从主列表中的特定范围构建子列表而不进行替换



真是一口!

作为实验的一部分,我生成了一个448项的数组。每个索引(项)如下所示:{'stimulus bin': 1, 'label': 2, 'stimID': 1, 'fileName': 'stim1.png'},应该作为一个整体进行选择。

现在,该主列表被细分为8个类别,每个类别包含56个项目(即:0-55、56-112、…、391-447。

以下是我希望能够做的事情:

我想创建14个子列表,这些子列表将从主列表中的8个类别中的每一个类别中随机选择4个索引,并从主列表中将其删除,这样特定索引只能选择一次(并将该选择添加到适当的列表中。

每个列表都可以命名为任意的名称,如list1-list14

最后我将列出14个清单,每个清单32项。

我很纠结该怎么做。我对Python有点陌生,不过我想我并不是完全一无所知。

任何建议都会对我很有帮助!

如果我理解正确,您有一个448项的列表(出于此算法的目的,这些项是不透明的)。它们的初始顺序决定了它们的类别,每组56个对应一个不同的类别(因此总共有8个类别)。

您想要得到14个列表的输出,每个列表中每个类别有四个项目。

以下是我将如何做到这一点的大纲:

  1. 首先,对列表进行切片以获得单独的类别
  2. 接下来,使用random.shuffle打乱类别列表
  3. 接下来,使用zip将包含56个项目的8个列表转换为包含8个项目的56个列表
  4. 接下来,在重复迭代器上再次使用zip,一次取四个值
  5. 最后,使用itertools.chain.from_iterable将值组合到最终列表中

代码:

import itertools
import random
def make_lists(input_list):
    categories = [input_list[i:i+56] for i in range(0, 448, 56)] # 8 lists of 56
    for c in categories:
        random.shuffle(c)
    selections = zip(*categories) # 56 tuples of 8
    it = iter(selections)
    by_four = zip(it, it, it, it) # 14 tuples of 4 tuples of 8
    results = [list(itertools.chain.from_iterable(lst)) for lst in by_four]
    return results

下面是一个在整数列表上运行此操作的示例:

>>> for lst in make_lists(list(range(448))):
    print(lst)
[47, 104, 114, 197, 269, 297, 368, 422, 23, 60, 128, 184, 242, 334, 375, 407, 6, 110, 160, 198, 244, 320, 383, 430, 27, 78, 153, 202, 272, 322, 376, 436]
[55, 67, 167, 211, 232, 284, 363, 420, 48, 73, 136, 190, 259, 332, 351, 440, 44, 64, 142, 180, 263, 294, 361, 419, 15, 83, 157, 207, 255, 280, 350, 398]
[12, 102, 124, 199, 252, 314, 341, 432, 53, 89, 147, 170, 265, 329, 369, 409, 36, 56, 155, 206, 241, 290, 366, 441, 5, 94, 140, 223, 262, 321, 388, 394]
[1, 81, 129, 203, 227, 319, 382, 421, 43, 57, 120, 173, 233, 292, 337, 428, 8, 58, 143, 196, 267, 301, 356, 403, 34, 101, 151, 194, 230, 300, 352, 435]
[11, 74, 112, 174, 250, 316, 391, 418, 38, 72, 132, 172, 261, 310, 338, 429, 13, 66, 144, 188, 275, 299, 347, 446, 31, 71, 119, 189, 248, 304, 367, 413]
[18, 109, 123, 208, 246, 323, 355, 416, 30, 85, 126, 192, 279, 303, 378, 406, 0, 103, 149, 179, 236, 333, 357, 408, 39, 75, 139, 187, 277, 285, 339, 400]
[9, 62, 121, 193, 271, 335, 385, 412, 19, 86, 116, 217, 264, 315, 380, 411, 42, 105, 154, 222, 256, 293, 387, 439, 29, 97, 130, 212, 273, 311, 348, 417]
[35, 90, 148, 186, 231, 331, 359, 433, 45, 76, 158, 182, 253, 317, 379, 405, 46, 106, 125, 218, 237, 325, 381, 444, 40, 84, 156, 205, 251, 283, 346, 397]
[17, 95, 159, 185, 268, 281, 353, 393, 54, 61, 134, 215, 258, 318, 342, 424, 22, 100, 135, 220, 254, 306, 365, 442, 41, 91, 137, 210, 257, 288, 370, 426]
[14, 68, 141, 177, 226, 330, 374, 415, 51, 87, 113, 216, 240, 287, 354, 437, 49, 96, 115, 200, 243, 313, 336, 404, 24, 92, 131, 214, 238, 296, 386, 447]
[32, 82, 162, 219, 274, 326, 358, 396, 7, 88, 118, 176, 224, 289, 384, 402, 16, 111, 122, 213, 234, 308, 340, 425, 10, 108, 164, 183, 225, 295, 373, 410]
[20, 77, 127, 195, 266, 312, 372, 392, 33, 70, 133, 168, 276, 328, 360, 427, 26, 99, 161, 209, 278, 291, 390, 401, 21, 80, 166, 181, 235, 298, 345, 399]
[52, 107, 117, 201, 270, 302, 377, 395, 37, 93, 150, 175, 228, 282, 344, 434, 25, 69, 163, 221, 239, 305, 343, 445, 3, 59, 152, 178, 247, 309, 364, 414]
[50, 65, 138, 171, 260, 324, 371, 443, 2, 63, 146, 191, 245, 286, 389, 438, 4, 98, 145, 204, 249, 307, 362, 431, 28, 79, 165, 169, 229, 327, 349, 423]

请注意,输出列表中项目的顺序并不是完全随机的,但任何给定项目都属于哪个列表。如果你希望输出中的项目按类别排序,你可能会颠倒第三步和第四步的顺序,但我认为这最终会有点尴尬,因为在列表理解中没有一种简单的方法来实现zip(it, it, it, it)技巧(我认为您需要两个列表理解,一个用于制作迭代器,另一个用于在有了it的名称后进行zip)。如果您需要输出列表按任何给定的顺序排列,我建议使用适当的key函数对每个列表进行排序。

448项的主列表可以实现为字典列表。它们根本不需要名字(如果你想的话,你可以在字典中添加另一个字段)。

masterList = []
for i in range(0, 8):
    for j in range(0, 56):
        category = []
        item = {'stimulus bin': 1, 'label': 2, 'stimID': 1, 'fileName': 'stim1.png'}
        category.append(item)
    masterList.append(category)

然后使用list.pop(i)(从列表的索引i中删除一个项目并返回它)和randint(a, b)ab之间的随机整数,包括两端)从每个类别中删除四个随机对象,并将它们粘贴到子列表中。

from random import randint
def sublist(masterList):
    result = []
    for category in masterList:
        for i in range(0, 4):
            result.append(category.pop(randint(0, len(category))))

该函数创建一个子列表。

最新更新