为列表 p 中出现在列表 s 中的项目的第一次出现追加 1,并为其他出现和 s 中的其他项目追加 0

Append 1 for the first occurence of an item in list p that occurs in list s, and append 0 for the other occurence and other items in s

我希望此代码为列表 p 中出现在列表 s 中的项目的第一次出现附加 1,并为其他出现和 s 中的其他项目附加 0。

下面是我当前的代码,它为所有出现的事件附加 1,我希望它仅为第一次出现的事件附加 1。求助

s = [20, 39, 0, 87, 13, 0, 23, 56, 12, 13]
p = [0, 13]
bin = []

for i in s:
        if i in p:        
            bin.append(1)      
        else:
            bin.append(0)
   

print(bin)

# current result [0, 0, 1, 0, 1, 1, 0, 0, 0, 1]
# excepted result [0, 0, 1, 0, 1, 0, 0, 0, 0, 0]

最简单的解决方案是从列表中删除项目 p 如果找到:

s = [20, 39, 0, 87, 13, 0, 23, 56, 12, 13]
p = [0, 13]

out = []
for i in s:
    if i in p:
        out.append(1)
        p.remove(i)
    else:
        out.append(0)

print(out)

打印:

[0, 0, 1, 0, 1, 0, 0, 0, 0, 0]

使用 index 查找列表中的第一个匹配项。

s = [20, 39, 0, 87, 13, 0, 23, 56, 12, 13]
p = [0, 13]
bin = [0] * len(s)
for value in p:
    bin[s.index(value)] = 1

看过一次的元素一定要记得。为此使用一套。

s = [20, 39, 0, 87, 13, 0, 23, 56, 12, 13]
p = [0, 13]
bin = []
seen = set()

for i in s:
    if i in p:
        if i in seen:
            bin.append(0)
        else:
            bin.append(1)
            seen.add(i)
    else:
        bin.append(0)

print(bin)

结果是[0, 0, 1, 0, 1, 0, 0, 0, 0, 0]

这只会遍历数据一次,不会修改任何输入值。


循环的压缩版本:

for i in s:
    if i in p and i not in seen:
        bin.append(1)
        seen.add(i)
    else:
        bin.append(0)

正如一些正确指出的那样,一些解决方案更改了 sp,因此 re-runs 不一致。所以要小心。

我会用一个很好的方法包装它:

import copy

def mark_first_key_occurence(values, keys):

  def account_for(v, c):
    if v not in c:
      return 0

    c.remove(v)
    return 1

  keys_copy = copy.deepcopy(keys)
  return [account_for(v, keys_copy) for v in values]

然后调用它:

s = [20, 39, 0, 87, 13, 0, 23, 56, 12, 13]
p = [0, 13]

print(mark_first_key_occurence(s, p))

更新:毫无疑问,凯利的解决方案是最好的。列表没有带有默认值的类似于 pop 的方法,但使用字典绝对是一个巧妙的技巧! 请感谢他。 这是我的小改动(我认为明确调用 pop 更干净)

d = dict.fromkeys(p, 1)
print([d.pop(i, 0) for i in s])
s = [20, 39, 0, 87, 13, 0, 23, 56, 12, 13]
p = [0, 13]
bin = [0]*len(s) # let the array contain only 0

for i in p: # for each element in p
    flag = False # this flag is made to true if the first occurence has been set to 1 in the bin array
    for j in range(len(s)):
        if((s[j]==i) and (not flag)):
            bin[j] = 1
            flag = True
print(bin)

更优雅的方式:

  s = [20, 39, 0, 87, 13, 0, 23, 56, 12, 13]
  p = [0, 13]
  bin = [1 if x in p else 0 for x in s]
  idxs = [idx for idx, item in enumerate(s) if item in s[:idx]]
  for idx in idxs:
      bin [idx] = 0
  print(bin)

[0, 0, 1, 0, 1, 0, 0, 0, 0, 0]

O(|s|+|p|) 时间并且不修改输入:(Try it online!):

d = dict.fromkeys(p, 1).pop
bin = [d(i, 0) for i in s]