如果__和__在___中,则

1 投票
3 回答
568 浏览
提问于 2025-04-16 15:30

我正在尝试创建一个脚本,用来遍历一个列表。

我需要查看一个有限的列表(有400个)能力标识符(比如124、129等,都是普通的整数)。

然后我有一个字典,用来记录每个用户拥有的能力。字典的键是用户名,而每个键对应的值是一个整数列表(也就是用户拥有的能力)。

举个例子:

User x - [124, 198, 2244 ...]
User Y - [129, 254, 198, 2244 ...]

我想要编制一个矩阵,显示每个能力与其他能力的出现频率,这个矩阵叫做邻接矩阵。

比如在上面的例子中,能力198和能力2244一起出现了两次。而能力254和124从未一起出现过。

我目前使用的代码是:

fe = []    
count = 0
competency_matches = 0
for comp in competencies_list:
    common_competencies = str("")
for comp2 in competencies_list:
    matches = int(0)
    for person in listx:
        if comp and comp2 in d1[person]:
            matches = matches + 1
        else:
            matches = matches
    common_competencies = str(common_competencies) + str(matches) + ","
fe.append(common_competencies)
print fe
print count
count = count + 1

但是这个代码不管用,只是返回每个能力总共出现了多少次。我觉得问题出在“if comp and comp2 in d1[person]:”这一行。

问题在于,比如说一个人拥有的能力是[123, 1299, 1236],如果我搜索能力123,这个能力会被返回两次,因为它出现在123和1236这两个条目中。有没有办法强制进行精确匹配,当使用“if __ and __ then”这种操作时。

或者有没有人有更好的建议来实现这个目标……

提前感谢任何指点。谢谢!

3 个回答

0

你这里的缩进表示你的两个循环并没有嵌套在一起。你首先会遍历一次 competencies_list,然后把 common_competencies 设置为空字符串,这个过程会重复400次。接着你又会遍历一次 competencies_list,然后做phooji解释的事情。我敢肯定,这不是你想要的结果。

3

这样做应该会快很多,因为它去掉了多余的一层循环。希望这对你有帮助。

from collections import defaultdict
from itertools import combinations

def get_competencies():
    return {
        "User X": [124, 198, 2244],
        "User Y": [129, 254, 198, 2244]
    }

def get_adjacency_pairs(c):
    pairs = defaultdict(lambda: defaultdict(int))
    for items in c.itervalues():
        items = set(items)  # remove duplicates
        for a,b in combinations(items, 2):
            pairs[a][b] += 1
            pairs[b][a] += 1
    return pairs

def make_row(lst, fmt):
    return ''.join(fmt(i) for i in lst)

def make_table(p, fmt="{0:>8}".format, nothing=''):
    labels = list(p.iterkeys())
    labels.sort()

    return [
        make_row([""] + labels, fmt)
    ] + [
        make_row([a] + [p[a][b] if b in p[a] else nothing for b in labels], fmt)
        for a in labels
    ]

def main():
    c = get_competencies()
    p = get_adjacency_pairs(c)
    print('\n'.join(make_table(p)))

if __name__=="__main__":
    main()

结果是

             124     129     198     254    2244
     124                       1               1
     129                       1       1       1
     198       1       1               1       2
     254               1       1               1
    2244       1       1       2       1        

... 显然,打印一个400列的表格到屏幕上有点多了;我建议使用csv.writer()把它保存到一个文件里,这样你就可以在Excel或OpenOffice中处理它。

8

你误解了and的用法。要检查两个值是否在一个列表中,可以使用:

if comp1 in d1[person] and comp2 in d1[person]:
  ...

你写的版本做的事情不一样。它的逻辑是这样的:if (comp1) and (comp2 in d1[person])。换句话说,它把comp1当作一个真假值来处理,然后再和你检查列表包含的部分做一个布尔and运算。这段代码是有效的,但它并没有实现你想要的效果。

撰写回答