在集合列表中查找唯一数字

时间:2015-09-17 18:36:55

标签: python set

我正在运行自己的小实验,需要一些代码帮助。

我正在创建一个列表,在索引位置0-99中存储100组,每个存储集存储1到100之间的随机数,这些随机数来自随机生成的包含100个数字的列表。

对于每组数字,我使用set()命令在将此组附加到列表之前过滤掉任何重复项...所以基本上我有一个包含1-100之间数字的100组列表。

我写了一些代码来检查每组的长度 - 我注意到我的设置通常是60-69个元素!基本上,所有数字中有1/3是重复的。

代码:

from random import randint

sets = []

#Generate list containing 100 sets of sets.
#sets contain numbers between 1 and 100 and no duplicates.

for i in range(0, 100):
    nums = []
    for x in range(1, 101):
        nums.append(randint(1, 100))
    sets.append(set(nums))


#print sizes of each set
for i in range(0, len(sets)):
    print(len(sets[i]))


#I now want to create a final set
#using the data stored within all sets to
#see if there is any unique value.

所以这就是我无法理解的一点......我想知道所有这些套装中是否有唯一的编号!我无法解决的是我如何去做。

我知道如果将一个集合存储在他们自己的变量中,我可以直接将它与另一个集合进行比较......但是我无法找到循环遍历集合列表的有效方法并将它们全部比较以创建一个新集合设置哪个,我希望,可能只包含一个唯一值!

我在文档中看到了这段代码......

s.symmetric_difference_update(t)

但我无法弄清楚如何将其应用到我的代码中。

非常感谢任何帮助!!

4 个答案:

答案 0 :(得分:1)

你可以使用一个Counter dict来计算在所有集合中保持值只有1的值:

from collections import Counter
sets = [{randint(1, 100) for _ in range(100)} for i in range(100)]

from itertools import chain

cn = Counter(chain.from_iterable(sets))
unique = [k for k, v in cn.items() if v == 1] # use {} to get  a set
print(unique)

要使元素仅对任何集合唯一,则列表中所有集合的元素数量必须为1。

如果我们使用一个简单的例子,我们添加一个绝对超出我们范围的值:

In [27]: from random import randint
In [28]: from collections import Counter  
In [29]: from itertools import chain
In [30]: sets = [{randint(1, 100) for _ in range(100)} for i in range(0, 100)]+ [{1, 2, 102},{3,4,103}]
In [31]: cn = Counter(chain.from_iterable(sets))   
In [32]: unique = [k for k, v in cn.items() if v == 1] 
In [33]: print(unique)
[103, 102]

如果要查找包含任何这些元素的集合:

In [34]: for st in sets:
   ....:     if not st.isdisjoint(unique):
   ....:            print(st)
   ....:         
set([1, 2, 102])
set([3, 4, 103])

对于您编辑过的部分问题,您仍然可以使用Counter.most_common来使用Counter dict来获取最小和最大值:

from collections import Counter
cn = Counter()

identified_sets = 0
sets = ({randint(1, MAX) for _ in range(MAX)} for i in range(MAX))

for i, st in enumerate(sets):
    cn.update(st)
    if len(st) < 60 or len(st) > 70:
        print("Set {} Set Length: {}, Duplicates discarded: {:.0f}% *****".
              format(i, len(st), (float((MAX - len(st)))/MAX)*100))
        identified_sets += 1
    else:
        print("Set {} Set Length: {}, Duplicates discarded: {:.0f}%".
              format(i, len(st), (float((MAX - len(st)))/MAX)*100))

#print lowest fequency
comm = cn.most_common()
print("key {} : count {}".format(comm[-1][0],comm[-1][1]))

#print highest frequency
print("key {} : count {}".format(comm[0][0], comm[0][1]))

print("Count of identified sets: {}, {:.0f}%".
      format(identified_sets, (float(identified_sets)/MAX)*100))

如果您在使用此代码和自己的代码创建集合之前致电random.seed(0),则会看到它们都返回相同的数字。

答案 1 :(得分:0)

你可以做到:

[Export]

答案 2 :(得分:0)

在查看评论之后,我决定采取一些不同的方式来实现我的目标。从本质上讲,我意识到我只是想在删除所有重复项后检查随机数生成器生成的数字的频率。我以为我可以通过使用集合删除重复项然后使用集合删除集合中的重复项来实现此目的......但这实际上并不起作用!!

我还注意到,有100组包含最多100个可能的数字,平均重复数字的数量约为30-40%。当您增加最大数量的集合,从而增加生成的最大数量时,丢弃的重复数字的百分比会以明确的模式减少。

经过进一步调查后,你可以算出丢弃数字的百分比 - 一旦生成一个数字,它就会达到命中相同数字的概率......

无论如何......感谢您的帮助!

代码已更新:

from random import randint

sets = []
identified_sets = 0

MAX = 100

for i in range(0, MAX):
    nums = []
    for x in range(1, MAX + 1):
        nums.append(randint(1, MAX))
    nums.sort()
    print("Set %i" % i)
    print(nums)
    print()
    sets.append(set(nums))


for i in range(0, len(sets)):
    #Only relevant when using MAX == 100
    if len(sets[i]) < 60 or len(sets[i]) > 70:
        print("Set %i Set Length: %i, Duplicates discarded: %.0f%s *****" %
              (i, len(sets[i]), (float((MAX - len(sets[i])))/MAX)*100, "%"))
        identified_sets += 1
    else:
        print("Set %i Set Length: %i, Duplicates discarded: %.0f%s" %
              (i, len(sets[i]), (float((MAX - len(sets[i])))/MAX)*100, "%"))


#dictionary of numbers
count = {}
for i in range(1, MAX + 1):
    count[i] = 0

#count occurances of numbers
for s in sets:
    for e in s:
        count[int(e)] += 1


#print lowest fequency
print("key %i : count %i" %
      (min(count, key=count.get), count[min(count, key=count.get)]))

#print highest frequency
print("key %i : count %i" %
      (max(count, key=count.get), count[max(count, key=count.get)]))

#print identified sets <60 and >70 in length as these appear less often
print("Count of identified sets: %i, %.0f%s" %
      (identified_sets, (float(identified_sets)/MAX)*100, "%"))

答案 3 :(得分:-1)

你也可以保留反转矩阵,这是从数字到这个数字所在的集合索引集合的映射。这个映射应该是gerenal中的dict(从数字到集合),但是一个简单的列表集合可以在这里做到这一点。 (我们也可以使用Counter,而不是保持整个反转矩阵)

from random import randint

sets = [set() for _ in range(100)]
byNum = [set() for _ in range(100)]

#Generate list containing 100 sets of sets.
#sets contain numbers between 1 and 100 and no duplicates.

for setIndex in range(0, 100):
    for numIndex in range(100):
        num = randint(1, 100)
        byNum[num].add(setIndex)
        sets[setIndex].add(num)


#print sizes of each set
for setIndex, _set in enumerate(sets):
    print(setIndex, len(_set))

#I now want to create a final set
#using the data stored within all sets to
#see if there is any unique value.

for num, setIndexes in enumerate(byNum)[1:]:
    if len(setIndexes) == 100:
        print 'number %s has appeared in all the random sets'%num