V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
HHH01
V2EX  ›  Python

Python 中 dict 的比较问题

  •  
  •   HHH01 · 2019-11-28 23:18:47 +08:00 · 4243 次点击
    这是一个创建于 1822 天前的主题,其中的信息可能已经有所发展或是发生改变。

    写了一个作业,比较两个单词,看前一个单词能否用后一个单词中的字母拼接出来。 Your task will be to write a function can_be_composed(word1, word2) to check if word1 can be composed from word2 . Put your function into a file compose.py. Example usages: • can_be_composed("python", "pantyhose") returns True • can_be_composed("python", "ponytail") returns False • can_be_composed("code", "docent") returns True • can_be_composed("messy", "reassembly") returns True • can_be_composed("computational", "alphanumeric") returns False • can_be_composed("linguistics", "criminologists") returns False

    思路是先把单词转换成 dict,然后再比较, import collections def word2dict(word):

    word2dict=dict(collections.Counter(word))
    
    return word2dict
    

    def can_be_composed(word1,word2): dw1=word2dict(word1) dw2=word2dict(word2)

    for key in dw1.keys():
        if key in list(dw2.keys()) and dw1[key] <= dw2[key]:
           return True
            
        else:
            return False
    

    但是我每次得出的都是 True,后来发现, for key in dw1.keys(): if key in list(dw2.keys()) and dw1[key] <= dw2[key]: return True

    这得出的结果是每个 key 的值的比较,输出的是一系列的对比结果,

    问题来了,对于 if key in list(dw2.keys()) and dw1[key] <= dw2[key]:,如何能够在对比只要得出 false 就输出 false,只有全部都是 True 才输出 true ?

    或者有没有更简单的方法?

    附上原题, Exercise 3. We will say that a word “can be composed” from another word if it is possible to select some of the letters from the second word (maybe all of them) to build the first one (possibly changing the order). For example, word “python” can be composed from words “pantyhose”, “immunotherapy”, or “hypnotists”. It can not be composed from word “ponytail” because “ponytail” does not have a letter “h”. Similarly, word “lesson” can be composed from “professional” or “responsible”, but it can not be composed from word “longest” as “longest” does not have enough “s” letters. Your task will be to write a function can_be_composed(word1, word2) to check if word1 can be composed from word2 . Put your function into a file compose.py. Example usages: • can_be_composed("python", "pantyhose") returns True • can_be_composed("python", "ponytail") returns False • can_be_composed("code", "docent") returns True • can_be_composed("messy", "reassembly") returns True • can_be_composed("computational", "alphanumeric") returns False • can_be_composed("linguistics", "criminologists") returns False Hint: Write a function word2dict(word) which will convert word to a dictionary with an information how many times every letter occured in word . Use word2dict in your can_be_composed function.

    18 条回复    2019-11-30 00:40:31 +08:00
    ipwx
        1
    ipwx  
       2019-11-28 23:35:30 +08:00   ❤️ 1
    >>> def can_be_composed(a, b):
    ... a_count = collections.Counter(a)
    ... b_count = collections.Counter(b)
    ... return all(a_count[k] <= b_count.get(k, 0) for k in a_count)
    HHH01
        2
    HHH01  
    OP
       2019-11-28 23:48:34 +08:00
    @ipwx 厉害。。。简单几个代码就把我一堆都简化了
    不多,.get(k,0)这一块不是很理解,为啥要有 0 ?
    cherbim
        3
    cherbim  
       2019-11-28 23:52:36 +08:00
    你知道你为啥每次都输出 True 呢,for 循环里面,return 直接返回值,停止方法,比如第一次循环,第一个单词第一个字母如果在第二个单词里,你 return true,直接这个方法就停止了,然后返回 ture,如果没有,返回 false,后面的都没比较,修改一下:return true 要放在 for 循环外面,return flase 放在 for 循环内部 ,判断字母在不在第二个里面 ,如果不在 return flase 如果在就 pass
    cherbim
        4
    cherbim  
       2019-11-29 00:00:44 +08:00
    @ryanjmliao dict.get(key, default=None) key -- 字典中要查找的键 default -- 如果指定键的值不存在时,返回该默认值 0 表示如果不存在返回 0,可以自己设定返回值
    ibirdyuan
        5
    ibirdyuan  
       2019-11-29 00:11:28 +08:00   ❤️ 2
    def can_be_composed(a, b):
    if set(a) - set(b):
    return False
    else:
    return True
    ljpCN
        6
    ljpCN  
       2019-11-29 00:21:08 +08:00 via Android   ❤️ 1
    @ibirdyuan 还可以写得更 Python 一点
    >>> def can_be_composed(a, b):
    ... return False if set(a) - set(b) else True
    noqwerty
        7
    noqwerty  
       2019-11-29 00:37:00 +08:00 via Android   ❤️ 1
    @ibirdyuan 这样应该不行吧,原题的要求是还要有足够数量的字母,比如 a 需要两个 y 而 b 只有一个 y 的话也会返回 False
    just1
        8
    just1  
       2019-11-29 00:37:14 +08:00   ❤️ 4
    @ljpCN #6 return bool(set(a) - set(b))
    ibirdyuan
        9
    ibirdyuan  
       2019-11-29 00:40:11 +08:00
    @noqwerty 你是对的,刚没看原题,以为就是一个判断子集的问题。
    刚发现原题有一句
    Similarly, word “lesson” can be composed from “professional” or “responsible”, but it can not be composed from word “longest” as “longest” does not have enough “s” letters.
    festoney8
        10
    festoney8  
       2019-11-29 01:59:10 +08:00
    word2 中逐个踢掉 word1 字母
    dji38838c
        11
    dji38838c  
       2019-11-29 04:41:59 +08:00   ❤️ 2
    搞那么多 bool, if 的干什么,集合里难道会没有子集的 operation 吗

    return set(b).issubset(set(a))
    ryanccq
        12
    ryanccq  
       2019-11-29 08:24:05 +08:00 via iPhone   ❤️ 1
    def can_be_composed(word1, word2):
    return all([word1.count(i) <= word2.count(i) for i in word1])
    hell0v2
        13
    hell0v2  
       2019-11-29 08:54:48 +08:00
    11 楼正式我想说的,不应该是思路问题么,这种情况用什么字典。。。
    yucongo
        14
    yucongo  
       2019-11-29 12:14:51 +08:00   ❤️ 1
    check = lambda x, y: all([y.count(elm) >= x.count(elm) for elm in x])

    check("python", "pantyhose") # True
    check('lesson', 'professional') # True
    check('lesson', 'responsible') # True
    check('lesson', 'longest') # False
    ipwx
        15
    ipwx  
       2019-11-29 12:22:36 +08:00 via Android
    楼上一堆没审题就来逼逼用集合差的家伙。
    imn1
        16
    imn1  
       2019-11-29 12:25:52 +08:00
    我建议变量 word2dict 改名
    变量和函数同名,return word2dict 这句会有问题吧?
    mixure
        17
    mixure  
       2019-11-29 15:39:29 +08:00   ❤️ 1
    我想知道 V2EX 怎么不让代码发出来乱七八糟的。

    ---

    from doctest import testmod
    def can_be_composed(word1,word2):
    """
    >>> can_be_composed('lesson', 'professional')
    True
    >>> can_be_composed('lesson', 'longest')
    False
    """
    word2=list(word2)
    try:
    [word2.remove(word) for word in word1]
    except ValueError:
    return False
    return True

    testmod()

    ---

    我在 Ipython 里面 用 time 试了以下,似乎比 1 楼的还快一些
    yucongo
        18
    yucongo  
       2019-11-30 00:40:31 +08:00
    楼上想法不错,一行实现,好像没办法 lambda 实现

    def check1(word1, word2): list2 = [*word2]; return not any([*map(lambda x: list2.remove(x) if x in list2 else True, word1)])

    check('lesson', 'responsible') # True
    check('lesson', 'longest') # False
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2835 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 15:03 · PVG 23:03 · LAX 07:03 · JFK 10:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.