【问题标题】:How to generate 2 list of tuples that are pairwise distinct如何生成2个成对不同的元组列表
【发布时间】:2021-02-02 06:01:03
【问题描述】:

我有 2 个从随机库生成的元组列表。

在每个列表本身中,没有重复项。 (使用random.sample()

生成两个列表以使它们成对不同的最简单(最 Pythonic)的方法是什么?

我拥有的当前代码:

 list1 = list(zip(random.sample(range(1, 100000), 2000), random.sample(range(1, 8000), 2000)))
 list2 = list(zip(random.sample(range(1, 100000), 3000), random.sample(range(1, 8000), 3000)))

例子:

list1 = [(1,1), (2,2), (3,3)]
list2 = [(1,1), (2,3), (1,3)] # Wrong, because (1,1) is already in list 1

list1 = [(1,1), (2,2), (3,3)]
list2 = [(1,2), (2,3), (1,3)] # Correct, as none of the tuples in list 1 is equal to list 2

列表中的元组是行和列。例如:(1,1) 表示第 1 行第 1 列。 所以如果 (1,1) 已经被 list1 占用了,那么它不应该被 list2 占用。

【问题讨论】:

  • 是否允许列表在同一行或同一列中有两个元素,只要它们不具有同一行同一列?
  • 例如,list1 是否可以同时包含(1, 1)(1, 2)? (那么(1, 1)list1(1, 2)list2 呢?)
  • 为什么不把列表加倍然后一分为二呢?
  • @user2357112supportsMonica 是的,这就是我想要的
  • 我认为@PatrickParker 的建议是最好的。除了,而不是两倍长,制作一个长度为(len_1 + len_2)的列表,然后用[:len_1][len_1:]切片,分别得到list_1list_2

标签: python python-3.x


【解决方案1】:

与其单独生成列表,不如生成一个大列表并对其进行切片。但是,您还需要修复现有列表生成的错误。

您现有的列表生成不仅仅是防止重复。它防止列表同时包含 (1, 1)(1, 2) - 它不是确保同一列表中的所有元组都是不同的,而是使所有第一个元素不同,所有第二个元素不同。

您需要从所有可能的元组中进行采样,或者等效地从一系列整数中进行采样,然后将其转换为元组:

max_row = 100000
max_col = 8000

len1 = 2000
len2 = 3000

big_sample = random.sample(range(max_row*max_col), len1+len2)
sample_as_coordinates = [(num // max_col + 1, num % max_col + 1) for num in big_sample]

list1 = sample_as_coordinates[:len1]
list2 = sample_as_coordinates[len1:]

【讨论】:

    【解决方案2】:

    您可以将列表转换为集合并获取它们的差异:

    list1 = [(1,1), (2,2), (3,3)]
    list2 = [(1,1), (2,3), (1,3)]
    
    set1 = set(list1).difference(set(list2))
    set2 = set(list2).difference(set(list1))
    
    print(list(set1))
    print(list(set2))
    
    #prints
    #[(3, 3), (2, 2)]
    #[(2, 3), (1, 3)]
    

    为确保保留原始随机列表的长度,可以将集合策略合并到递归函数中,如下所示:

    def create_unique(length1, length2):
        list1 = list(zip(random.sample(range(1, 100000), length1), random.sample(range(1, 8000), length1)))
        list2 = list(zip(random.sample(range(1, 100000), length2), random.sample(range(1, 8000), length2)))
    
        intersect = set(list1).intersection(set(list2))
        #base case
        if not intersect:
            return list1, list2
        #recursive case
        return create_unique(length1 - len(intersect), length2 - len(intersect))
    
    a = create_unique(2000,3000)
    
    #a is a tuple of two non-overlapping sets of tuples of specified lengths
    print(len(a[0])) #2000
    print(len(a[1])) #3000
    

    【讨论】:

    • 如果我这样做,那么列表的大小将不正确。在您的示例中从长度 = 3 到长度 = 2
    • @Kai 我明白了。请参阅我修改后的解决方案,该解决方案使用递归函数来确保保留原始列表的长度。
    【解决方案3】:

    枚举 list2 并检查是否在 list1 中的项目。生成一个在 list1 中找不到的唯一元组,并将 list2 元组替换为等于 list1 元组。使用 set 查看结果集是否唯一。使用叉积和计数器来查看是否有任何组合是非唯一的。

     import random
     from random import sample
    
     list1 = list(zip(sample(range(1, 100000), 20), sample(range(1, 80000), 20)))
     list2 = list(zip(sample(range(1, 100000), 30), sample(range(1, 80000), 30)))
    
     for item in list2:
          for index,item2 in enumerate(list1):
               if item==item2:
                    replace_tuple=random.choice(range(1, 100000)),random.choice(range(1, 100000))
                    while replace_tuple in list1:
                       replace_tuple=random.choice(range(1, 100000)),random.choice(range(1, 100000))
                       list2[index]=replace_tuple
    
      print("list1 test for uniqueness",len(list1)==len(set(list1)))            
      print("list2 test for uniqueness",len(list2)==len(set(list2)))
    
      #second test for uniqueness between the two lists
    
      import itertools
      results=[*itertools.product(list1,list2)]
      #print(results)
    
      from collections import Counter
      cntr=Counter(results)
      if max(cntr.values())>1:
          print('failed')
      else
          print('no duplicates')
    

    【讨论】:

      猜你喜欢
      • 2022-11-22
      • 1970-01-01
      • 2018-09-06
      • 1970-01-01
      • 2020-06-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-16
      • 1970-01-01
      相关资源
      最近更新 更多