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

关于 Python 表达包含与被包含的语法

  •  
  •   kevinfk2 · 2020-12-18 10:36:15 +08:00 · 3040 次点击
    这是一个创建于 1470 天前的主题,其中的信息可能已经有所发展或是发生改变。
    例如两个数据对比

    A: aabbcc

    B: abbc

    如果 A 包含 B,就输出 。

    用什么表达语法啊

    新手求解,大佬莫怪
    第 1 条附言  ·  2020-12-18 14:24:59 +08:00
    首先感谢各位大佬的耐心解答。但是新手看完回答后还是很懵。我改成一个实际的例子说明吧。

    现在有两个 excel 。

    excel A 的数据是 https://imgur.com/qv4tUV9
    excel B 的数据是 https://imgur.com/0hLpmRJ

    现在我需要用 A 去和 B 对照,找出两个表类类似的数据(就是 A 和 B 两个表中有的名字是完全一样的,有的是不完全一样的)。

    我现在用的代码是
    # -*- coding: utf-8 -*-
    from __future__ import print_function

    import xlrd

    file1 = r'C:\Users\140082\Desktop\test_待检测数据.xlsx' # 待检测文件路径
    file2 = r'C:\Users\140082\Desktop\test_对照表格.xlsx' # 对照文件路径

    def compare(file1, file2):
    nickName = [] # 存放所有不存在的数据在待检测表格中的索引
    wb1 = xlrd.open_workbook(file1) # 打开待检测 xlsx 文件
    wb2 = xlrd.open_workbook(file2) # 打开对照 xlsx 文件
    sheet1 = wb1.sheet_by_index(0) # 参数 0 是索引,表示 wb1 这个文件的第一张表格
    sheet2 = wb2.sheet_by_index(0) # 和上同理
    for i in sheet1.col_values(0): #遍历 sheet1 中第一列每一项

    if i in sheet2.col_values(0): #查看是否在 sheet2 第一列中

    nickName.append(i)
    return nickName #返回的是不存在于 sheet2 中的数据的第一列的值的列表
    print(compare(file1, file2))

    运行后,只有两个表完全一样的数据才输出了。怎么改进能得到我想要的结果呢?
    38 条回复    2020-12-21 11:24:27 +08:00
    destinism
        1
    destinism  
       2020-12-18 10:53:35 +08:00
    B in A 吧
    galileo1214
        2
    galileo1214  
       2020-12-18 10:55:22 +08:00
    isin
    whitefox027
        3
    whitefox027  
       2020-12-18 10:58:46 +08:00
    if B in A :
    kevinfk2
        4
    kevinfk2  
    OP
       2020-12-18 10:59:17 +08:00
    @destinism B in A 好像只能对比完全一致的两个数据,我想对比的是两个类似的数据。不知道用什么表达好
    zeroDev
        5
    zeroDev  
       2020-12-18 11:00:44 +08:00 via Android
    @kevinfk2 #4 就是这样用的,你自己试试
    ly4572615
        6
    ly4572615  
       2020-12-18 11:01:26 +08:00
    那用正则吧
    kevinfk2
        7
    kevinfk2  
    OP
       2020-12-18 11:01:45 +08:00
    @galileo1214 我试试
    ly4572615
        8
    ly4572615  
       2020-12-18 11:02:14 +08:00
    或者 find()方法
    kevinfk2
        9
    kevinfk2  
    OP
       2020-12-18 11:07:04 +08:00
    @ly4572615 不太会我找找用法试下先
    destinism
        10
    destinism  
       2020-12-18 11:07:44 +08:00
    @kevinfk2 那只能正则了
    LiKanKan
        11
    LiKanKan  
       2020-12-18 11:09:53 +08:00 via Android
    A:str = "aabbcc"
    B:str = "abbc"
    if A.find(B) == -1:
    #找不到为-1,如果找到则为第一个出现的位置
    print("B is not in A")
    else:
    print("A contains B")
    kevinfk2
        12
    kevinfk2  
    OP
       2020-12-18 11:20:13 +08:00
    @LiKanKan 那如果是对 list 而言的话,该怎么用啊
    HashV2
        13
    HashV2  
       2020-12-18 11:52:07 +08:00
    @kevinfk2 如果你是只是想无序的判断 B 列表内所有的元素在不在另 A 列表中遍历就好了:
    all([ele in A for ele in B])
    如果想有序判断可以先在 A 中找到 B 的第一个元素的所有的索引
    按照 B 的长度从索引切片后和 B 比较,如果有一个为真就是有序包含了
    LiKanKan
        14
    LiKanKan  
       2020-12-18 12:08:47 +08:00 via Android   ❤️ 1
    @kevinfk2 如果是 List[str]可以用"".join(A 或 B)转化成上面一种情况。如果包含其他种类元素:如果连续有序,就手写子串匹配;如果不连续有序,就遍历 B,对着 A 的元素找;如果不连续也不有序,反之,对遍历 A 找 B
    no1xsyzy
        15
    no1xsyzy  
       2020-12-18 12:38:56 +08:00
    @HashV2 把方括号去掉获得空间和时间提升( compl 换成 compg,不需要存储整个 list,第一个为 False 的地方直接退出)
    当然,从可读性上来说,如果都是 hashable 的话,推荐 set(A) > set(B)

    @kevinfk2 list 就是正常手写循环啊(
    的确有双层 compg 的黑魔法,但可读性太垃圾了。
    009694
        16
    009694  
       2020-12-18 12:56:59 +08:00 via iPhone
    为啥要用 find 不用 in 。。find 比 in 慢得多 (从 js 转的还是 java 转的?
    JeffGe
        17
    JeffGe  
       2020-12-18 13:19:26 +08:00
    >>> A = [1, 1, 2, 2, 1, 1]
    >>> B = [1, 2, 2, 1]
    >>> str(B)[1:-1] in str(A)
    True
    kevinfk2
        18
    kevinfk2  
    OP
       2020-12-18 14:28:06 +08:00
    @LiKanKan 看了下还没弄明白,我加了附言,可能更方便你帮我解答,有时间的话帮我看看呗
    ipwx
        19
    ipwx  
       2020-12-18 14:42:51 +08:00
    你需要某种字符串相似度计算的算法,比如编辑距离( edit distance )

    https://leetcode.com/problems/edit-distance/
    https://pypi.org/project/editdistance/0.3.1/
    ipwx
        20
    ipwx  
       2020-12-18 14:44:07 +08:00
    在做一些根据先验知识的预处理。比如后缀“有限公司”或者“公司”就先全部删掉。
    JeffGe
        21
    JeffGe  
       2020-12-18 14:47:23 +08:00 via Android   ❤️ 1
    if any(i in s2 for s2 in sheet2.col_values(0)):
    owtotwo
        22
    owtotwo  
       2020-12-18 14:48:44 +08:00 via Android   ❤️ 1
    你得先定义什么是“相似” 再谈其他的
    kevinfk2
        23
    kevinfk2  
    OP
       2020-12-18 14:55:52 +08:00
    @JeffGe 感谢大佬,出效果了 十分感谢!
    lanshee
        24
    lanshee  
       2020-12-18 14:59:57 +08:00
    if A in B or B in A 这样行不?
    kevinfk2
        25
    kevinfk2  
    OP
       2020-12-18 15:02:34 +08:00
    @lanshee 好像不行吧 我没试 in 好像都是查完全一致的才行
    sudoy
        26
    sudoy  
       2020-12-18 15:04:12 +08:00
    我看你好像只遍历一个数据,两个都要遍历。

    ```
    a = ['苹果', '橘子', '香蕉', ‘葡萄’]
    b = ['苹果', ‘越南橘’, '香蕉', '椰子']

    c = []
    for x in a:
    for y in b:
    if x == y:
    c.append(x)
    ```
    sudoy
        27
    sudoy  
       2020-12-18 15:09:26 +08:00
    或者

    a = ['苹果', '橘子', '香蕉', ‘葡萄’]
    b = ['苹果', ‘越南橘’, '香蕉', '椰子']
    c = [x for x in a if x in b]

    c 应该就是你要找的
    sudoy
        28
    sudoy  
       2020-12-18 15:10:30 +08:00
    >>> a = ['apple', 'orange', 'banana']
    >>> b = ['apple', 'grape', 'banana']
    >>> c = [x for x in a if x in b]
    >>> c
    ['apple', 'banana']
    sudoy
        29
    sudoy  
       2020-12-18 15:20:20 +08:00   ❤️ 1
    如果你要模糊匹配,可以为:

    >>> a = ['apple', 'orange', 'banana']
    >>> b = ['apple', 'grape', 'fresh banana']
    >>> c = []
    >>> for x in a:
    ...............for y in b:
    ........................if x == y or x in y:
    ...............................c.append(x)
    lanshee
        30
    lanshee  
       2020-12-18 15:21:02 +08:00
    @sudoy 你这个少遍历了吧,这个是全量匹配了.他的需求应该是当前单词在不在另一组的单词里,而不是在另一组里
    sudoy
        31
    sudoy  
       2020-12-18 15:28:35 +08:00
    @lanshee 嗯,我前面没看清楚,最后一个回复里面考虑到得了。不过这里面还有特殊字符的问题,另外还有可能要把名字拆开匹配,比如“某某公司”和“某某有限责任公司”属于同一家公司,那么就要把前面拆成四个字,后面拆成八个字,如果后面那八个字都包含前面四个字,就是满足条件
    duzhor
        32
    duzhor  
       2020-12-18 15:28:38 +08:00
    你这个 if 的意思是如果 sheet1 的元素在 sheet2 的列表里面。所以要加一层 for 去遍历 sheet2,再把 sheet1 里的每个元素依次跟 sheet2 里的每个元素比较。
    TimePPT
        33
    TimePPT  
       2020-12-18 15:40:47 +08:00   ❤️ 1
    字符串匹配策略遇到
    翰硕电子 | 翰碩電子
    这种 case 你没法解的
    est
        34
    est  
       2020-12-18 15:49:01 +08:00
    @TimePPT 正解了。

    所以 LZ 这个事其实还是手动做的好。。
    xuqiccr
        35
    xuqiccr  
       2020-12-18 15:50:20 +08:00
    BTW,处理 Excel 试试 pandas
    kevinfk2
        36
    kevinfk2  
    OP
       2020-12-18 16:02:38 +08:00
    @est 这只是个例子 要处理的数据有几 w 个
    krixaar
        37
    krixaar  
       2020-12-18 17:22:00 +08:00
    如果真的只是差“有限公司”或者“有限责任公司”这样,可以直接把另一边的数据先处理了再比对。
    问题是规则是不是就这么简单,比如碰到农行、农发行、农业银行、农业发展银行这样的。
    HelloViper
        38
    HelloViper  
       2020-12-21 11:24:27 +08:00
    以前的公司名匹配度算法供参考:
    https://github.com/verarong/CompanyNameMatch
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5490 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 06:02 · PVG 14:02 · LAX 22:02 · JFK 01:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.