简体   繁体   English

如何获取python字典或大小为X的列表,并为每个元素分配字典本身的Y个随机索引值

[英]How do I take a python Dictionary or List of size X and assign each element with Y random index values of the dictionary itself

I'm not sure if it would be best to use a list or a dictionary for this algorithm. 我不确定这种算法是否最好使用列表或字典。 Assuming I use a dictionary, I want to create a dictionary of size X and randomly assign each element with Y index values of the dictionary itself. 假设我使用字典,我想创建一个大小为X的字典,并为每个元素随机分配字典本身的Y索引值。

Meaning I could take a dictionary of size 5, and assign each of those 5 elements with 2 index values ranging between 1-5. 意思是我可以选择一个大小为5的字典,并为这5个元素中的每个元素分配2个索引值,范围在1-5之间。

The constraints would be that the index value can not be assigned to its own index, so the 2nd index can only be assigned values 1,3,4,5; 约束条件是不能将索引值分配给它自己的索引,因此只能为第二个索引分配值1,3,4,5; And Y must always be less that X, in order to prevent assigning duplicate index values to the same index. 并且Y必须始终小于X,以防止将重复的索引值分配给同一索引。

What I have so far is being done with a list rather than a dictionary, but I'm not sure if this is the best method. 到目前为止,我所要做的只是列表而不是字典,但是我不确定这是否是最好的方法。 I'd like to keep the algorithm running at 0(n) speed as well, even if the size of the list/dictionary is huge. 我希望算法也以0(n)的速度运行,即使列表/字典的大小很大。 Either way, this is where I'm at. 无论哪种方式,这就是我所在的位置。

So, I make X a list of size 5. I set Y equal to 3, meaning I want each of those 5 elements to contain 3 index values. 因此,我使X成为大小为5的列表。我将Y设置为等于3,这意味着我希望这5个元素中的每一个都包含3个索引值。 In the for-loop I create another list excluding the index value I'm currently assigning values to. 在for循环中,我创建另一个列表,但不包括我当前正在为其分配值的索引值。

X = range(5)[::1] # [0, 1, 2, 3, 4]
print(X)
Y = 3    
assigned = []

for k in range(0, len(X)):  
    XExcluded = [x for i,x in enumerate(X) if i!=k]   # if k==3 then [0, 1, 2, 4]
    print("EXcluded: {}" .format(XExcluded))

    assigned.append(list(random.sample(XExcluded, Y)))
    print("assigned: {}" .format(assigned))

Sample Output: 样本输出:

[0, 1, 2, 3, 4]
EXcluded: [1, 2, 3, 4]
assigned: [[1, 2, 3]]
EXcluded: [0, 2, 3, 4]
assigned: [[1, 2, 3], [3, 2, 4]]
EXcluded: [0, 1, 3, 4]
assigned: [[1, 2, 3], [3, 2, 4], [3, 4, 1]]
EXcluded: [0, 1, 2, 4]
assigned: [[1, 2, 3], [3, 2, 4], [3, 4, 1], [0, 1, 2]]
EXcluded: [0, 1, 2, 3]
assigned: [[1, 2, 3], [3, 2, 4], [3, 4, 1], [0, 1, 2], [2, 3, 1]]

One thing I would really like to implement is someway to average out which index values are being assigned over time, because right now the algorithm may assign certain index values more than others. 我真正想要实现的一件事是某种程度上求出随着时间的推移分配哪些索引值,因为现在该算法分配的某些索引值可能比其他算法更多。 This may be more apparent when starting with smaller lists, but I'd imagine this wont be as much of a problem when starting with a very large list since it would allow the randomly sampled index values to better average out over time. 当从较小的列表开始时,这可能更明显,但是我想当从非常大的列表开始时,这不会有太大的问题,因为它将允许随机采样的索引值随时间更好地平均。

To balance selections, in the case of your example, where X and Y are both small, a naive solution would be checking which value is missing in each iteration and adding that value to next round to add additional weighting for it during random sampling. 为了平衡选择,在您的示例中,X和Y都很小,一个幼稚的解决方案是检查每次迭代中缺少哪个值,并将该值添加到下一轮以在随机采样期间为其添加更多权重。

Below is just a simple workable example, without too much effort in efficiency optimization. 以下仅是一个简单的可行示例,而无需花费太多精力进行效率优化。 You may consider using other data structure than set for optimization. 您可能会考虑使用其他数据结构而不是为优化设置的数据结构。 (Diff in sets takes O(n). At the end it may get to O(n^2). Since this is aimed at short list case, set was chosen for its simplicity in code.) (集合中的差异取O(n)。最后,它可能达到O(n ^ 2)。由于这是针对短列表的情况,因此选择集合是因为​​其代码简单)。

import random

X = set(range(5)[::1]) # assume you have distinct values as shown in your example
Y = 3
assigned = []
tobeweighted=None

def assigned_and_missing(fullset, index):
  def sample(inlist, weighteditem, Y):
    if weighteditem is not None:
      inlist.append(weighteditem)
    print("Weighted item: {}" .format(weighteditem))
    print("Interim selection (weighted item appended): {}" .format(inlist))
    randselection = set(random.sample(inlist, Y))
    remain = fullset - set((index+1,)) - randselection   
    missingitem = remain.pop()
    if len(randselection) < Y:
      randselection.add(remain.pop())
    return randselection, missingitem
  return sample


for k in range(0, len(X)):
    weighted_random = assigned_and_missing(X, k)
    XExcluded = [x for i,x in enumerate(X) if i!=k]   # if k==3 then [0, 1, 2, 4]

    print()
    print("EXcluded: {}" .format(XExcluded))

    selection, tobeweighted = weighted_random(XExcluded, tobeweighted, Y)
    print("Final selection: {}" .format(selection))

    assigned.append(selection)
    print("assigned: {}" .format(assigned))
    print("Item needs to be weighted in next round: {}" .format(tobeweighted))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM