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
wuwukai007
V2EX  ›  Python

Python 碰到一题,大家有没有更好的解法

  •  
  •   wuwukai007 · 2021-07-22 21:17:12 +08:00 · 3024 次点击
    这是一个创建于 980 天前的主题,其中的信息可能已经有所发展或是发生改变。
    nput_data = [
        ['格力', '格力电器'],
        ['格力', '美的', '格力电器', '美的集团'],
        ['中国民生投资股份有限公司', '中民投'],
        ['格力', '格力电器', '格力集团'],
        ['工银', '中信证券', '工行', '中国工商银行'],
        ['建行', '建设银行', '北大光华'],
        ['中国银行', '工行', '工商银行', '港交所'],
        ['中行', '建行', '工行', '中金', '工商银行', '中国银行', '建设银行'],
        ['农行', '建设银行', '建行', '中行'],
        ['中国民生投资股份有限公司', '上海金融法院', '中民投', '启信宝']
    ]
    输出:
                {('格力', '格力电器'): 3,
                 ('美的', '美的集团'): 1,
                 ('中民投', '中国民生投资股份有限公司'): 2,
                 ('格力', '格力集团'): 1,
                 ('工银', '中国工商银行'): 1,
                 ('建行', '建设银行'): 3,
                 ('中行', '中国银行'): 2,
                 ('工银', '工商银行'): 2}
    
    
    from itertools import chain
    from collections import defaultdict
    
    data = list(chain(*nput_data))
    res = [set(i) for i in data]
    
    count = defaultdict(int)
    for index,row in enumerate(res):
        for index2,i in enumerate(res):
            if row.issuperset(i) and row != i:
                count[(data[index2],data[index])] += 1
                break
            
    
    第 1 条附言  ·  2021-07-22 22:18:51 +08:00
    原题就是 
    nput_data = [xx] ,
    结果是: 
    ('格力', '格力电器'): 3, 
    ('格力', '格力集团'): 1, 等,请补全结果,
    我也是嗯做,然后说是 key 全包含另一个 key 作为一个分类,
    统计所有分类数量
    key1 全包含 key2 就算一类,例如 '中国民生投资股份有限公司' 包含 '中民投'
    
    21 条回复    2021-07-24 01:25:11 +08:00
    imn1
        1
    imn1  
       2021-07-22 22:02:53 +08:00
    问题:
    这些 key 是怎么定的?例如"工银","工商银行"这个 2 是怎么出来的?还分词么?
    wuwukai007
        2
    wuwukai007  
    OP
       2021-07-22 22:05:10 +08:00
    @imn1 key1 全包含 key2 就算一类,例如 '中国民生投资股份有限公司' 包含 '中民投'
    noparking188
        3
    noparking188  
       2021-07-22 22:10:56 +08:00
    麻烦把原题贴出来,连定义都没有
    wuwukai007
        4
    wuwukai007  
    OP
       2021-07-22 22:17:07 +08:00
    @noparking188 原题就是 nput_data = [xx] ,结果是: ('格力', '格力电器'): 3, ('格力', '格力集团'): 1,, 等,请补全结果,我也是嗯做,然后说是 key 全包含另一个 key 作为一个分类,统计所有分类数量
    menc
        5
    menc  
       2021-07-22 22:17:39 +08:00

    from itertools import combinations
    生成所有组合数,避免自己手写,但是顺序不固定,记得用长度 sort 一下
    menc
        6
    menc  
       2021-07-22 22:18:13 +08:00
    from itertools import combinations
    from collections import defaultdict

    result = defaultdict(int)
    for line in nput_data:
    combs = combinations(line, 2)
    for comb in combs:
    comb_ = sorted(comb, key=lambda x:len(x))
    if set(comb_[1]).issuperset(set(comb_[0])):
    result[tuple(comb_)] += 1
    menc
        7
    menc  
       2021-07-22 22:18:26 +08:00
    ```python
    from itertools import combinations
    from collections import defaultdict

    result = defaultdict(int)
    for line in nput_data:
    combs = combinations(line, 2)
    for comb in combs:
    comb_ = sorted(comb, key=lambda x:len(x))
    if set(comb_[1]).issuperset(set(comb_[0])):
    result[tuple(comb_)] += 1
    ```
    menc
        8
    menc  
       2021-07-22 22:18:46 +08:00
    不支持贴代码啊。。。
    理解思想好了(
    wuwukai007
        9
    wuwukai007  
    OP
       2021-07-22 22:19:41 +08:00
    @menc 谢谢。我看下 combinations 怎么用,没用过
    imn1
        10
    imn1  
       2021-07-22 22:41:27 +08:00
    key 肯定要另外算,值反而是小事,key 出来后 groupby,count 一下就行了
    imn1
        11
    imn1  
       2021-07-22 22:52:27 +08:00
    ('工银', '工商银行'): 2
    这个如果没有写错的话,是最大问题,如果是'工行',那还可以理解为每行行内匹配|组合
    如果是'工银'无误,那就变成跨行匹配了('工银'只出现一次,这个 2 搞得很混乱,不知道怎么来的),跨行匹配就应该有 ('中国银行', '中国工商银行') 这种组合

    有些细则没有写明,例如第一个 key 是否有字数限制,能否跨行匹配等等
    O5oz6z3
        12
    O5oz6z3  
       2021-07-23 02:15:53 +08:00
    不知道对不对,花里胡哨做法两则如下:
    exec('''
    from itertools import chain
    from collections import Counter
    from pprint import pprint as pp

    # from functools import lru_cache
    # _set = lru_cache(None)(set)
    # issupset = lambda x,y: _set(x).issuperset(_set(y)) and x!=y

    # nput_data = ……
    issupset = lambda x,y: set(x).issuperset(set(y)) and x!=y
    all = list(chain.from_iterable(nput_data))
    any = set(all)

    print('如果不重复匹配')
    hits = []
    for x in all:
    \t for y in any:
    \t\t if issupset(x, y):
    \t\t\t hits.append((y, x))
    \t\t\t break
    pp(Counter(hits))

    print('如果重复匹配')
    from itertools import product
    res = filter(lambda a:issupset(*a), product(all, any))
    ctr = Counter((y,x) for x,y in res)
    pp(ctr)
    ''')
    <del>(答对有奖吗)</del>
    Xs0ul
        13
    Xs0ul  
       2021-07-23 03:59:48 +08:00
    需求不明确,打回去重写(

    但作为一个需求,看起来是根据上下文,找出缩写。缩写就定义成每个字都在另一个字符串中。然后统计所有缩写的数量
    ericgui
        14
    ericgui  
       2021-07-23 06:50:31 +08:00
    你就遍历呗,性能再差能差到哪里
    zzl22100048
        15
    zzl22100048  
       2021-07-23 08:09:00 +08:00 via iPhone
    按字拆分取倒排索引,查询的时候取交集
    wuwukai007
        16
    wuwukai007  
    OP
       2021-07-23 08:14:16 +08:00
    @O5oz6z3 没有呢😀
    O5oz6z3
        17
    O5oz6z3  
       2021-07-23 08:20:48 +08:00
    @wuwukai007 啊这,所以答对了?
    wuwukai007
        18
    wuwukai007  
    OP
       2021-07-23 09:29:31 +08:00
    @O5oz6z3 没有标准答案啊,只有最优解
    O5oz6z3
        19
    O5oz6z3  
       2021-07-23 09:40:15 +08:00
    @wuwukai007 好吧,那最后一个问题,题目是要求 key1 只能匹配一种 key2 ?还是说 key1 可以匹配多种 key2 ?比如 “中国工商银行” 可以分类到 “工银”、“中行” 或者 “工行” 等等。
    araraloren
        20
    araraloren  
       2021-07-23 10:55:02 +08:00
    感觉比较科学的就是 按 顺序 和 单字 来匹配.. 毕竟缩写的字不一定相连
    O5oz6z3
        21
    O5oz6z3  
       2021-07-24 01:25:11 +08:00
    @O5oz6z3 #12 订正一下,重看了题目后发现 #12 楼的做法是错的。
    正如 #3 楼所说,虽然不知道是什么题目描述居然很模糊,还没有标准答案,不过大意我猜是像 #13 楼所说在每行列表内搜索所有可能的缩写组合,也就是如 #11 楼所说不能跨行匹配。最后统计所有缩写组合的出现次数。正确的思路应该是如 #5 楼那样使用组合排列之类的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3394 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:40 · PVG 18:40 · LAX 03:40 · JFK 06:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.