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

Python 怎么优雅的实现 Ruby 的('a'..'z').to_a 操作?

  •  
  •   kzing · 2014-06-19 23:31:20 +08:00 · 8944 次点击
    这是一个创建于 3844 天前的主题,其中的信息可能已经有所发展或是发生改变。
    单纯的实现从'a'到'z'的遍历不难, 但是如果要实现这样的
    输入: ('ab'..'xy').to_a

    输出: ["ab", "ac", "ad",... ... ,"xw", "xx", "xy"]

    可能就比较复杂

    有比较Pythonic的方法或者算法吗?
    第 1 条附言  ·  2014-06-20 15:19:32 +08:00
    题主正在面壁反思ing...

    补充一下描述

    在Ruby中:
    ('a'..'bc').to_a 输出:

    ["a", "b", "c",... ..., "z", "aa", "ab", "ac", ... ..., "ay", "az", "ba", "bb", "bc"]

    甚至

    ('ab', 'cd').to_a 输出:

    ["ab", "ac", "ad", ... ..., "az", "ba", "bb", "bc", "bd", ... ..., "bz", "ca", "cb", "cc", "cd"]
    第 2 条附言  ·  2014-06-20 15:19:55 +08:00
    题主正在面壁反思ing...

    补充一下描述

    在Ruby中:
    ('a'..'bc').to_a 输出:

    ["a", "b", "c",... ..., "z", "aa", "ab", "ac", ... ..., "ay", "az", "ba", "bb", "bc"]

    甚至

    ('ab', 'cd').to_a 输出:

    ["ab", "ac", "ad", ... ..., "az", "ba", "bb", "bc", "bd", ... ..., "bz", "ca", "cb", "cc", "cd"]
    44 条回复    2020-06-16 11:50:19 +08:00
    RIcter
        1
    RIcter  
       2014-06-19 23:34:03 +08:00
    ddzz
        2
    ddzz  
       2014-06-19 23:38:51 +08:00
    这种花拳绣腿功能是专门用来打广告的
    orancho
        3
    orancho  
       2014-06-19 23:40:34 +08:00
    笑看二楼无脑黑,懒得吵,好不好用自己心里知道
    RIcter
        4
    RIcter  
       2014-06-19 23:42:27 +08:00
    @orancho 幫你@一下>_>
    cc @ddzz
    manfay
        5
    manfay  
       2014-06-19 23:46:41 +08:00
    S1 = 'abcdefghijklmnopqrstuvwx'
    S2 = 'bcdefghijklmnopqrstuvwxy'
    L = [a+b for a in S1 for b in S2]
    orancho
        6
    orancho  
       2014-06-19 23:47:26 +08:00
    @RIcter 不用,已经blocked了
    kzing
        7
    kzing  
    OP
       2014-06-20 00:23:27 +08:00
    @RIcter 这个模块大家都会, 但是你贴这个链接似乎对我没有什么帮助 :)
    kzing
        8
    kzing  
    OP
       2014-06-20 00:25:11 +08:00
    @ddzz :) 这么看来, Ruby中很多我认为很酷的功能都是花拳绣腿啊
    kzing
        9
    kzing  
    OP
       2014-06-20 00:27:05 +08:00
    @manfay 不错唉, 提供了一个思路. 谢谢.
    RIcter
        10
    RIcter  
       2014-06-20 00:28:58 +08:00
    @kzinglzy 我发的链接稍微看一下里面的内容啊,有实现的
    kzing
        11
    kzing  
    OP
       2014-06-20 00:31:05 +08:00
    @RIcter 不会吧= =! 自认已经看过很多遍Itertools模块了, 指点一下?
    incompatible
        12
    incompatible  
       2014-06-20 00:37:03 +08:00
    卧槽 搞java和groovy的完全看不懂你们在说什么

    到底什么场景下会需要遍历'ab'-'xy'这些玩意儿??
    kzing
        13
    kzing  
    OP
       2014-06-20 00:48:47 +08:00
    @incompatible 也许可以类比一下Linux? 比如要生成某些连续的文件; 又比如做爬虫时遍历一连串有规律的渐变的URL? 再比如做算法题的时候需要一个映射数字到字母组合的映射? 懂得少, 没想出必须要用到的地方. 但我觉得存在即意义, 如果一点用都没有的话, 我也就不会从Ruby文档看到这个了:)

    我的本意是交流这个问题的Pythonic实现. 谢谢.
    mulog
        14
    mulog  
       2014-06-20 00:53:35 +08:00
    s = string.ascii_lowercase
    result = [t[0]+t[1] for t in itertools.product(s, repeat=2)]
    # or
    result = [a+b for a in s for b in s]

    其实没太看懂你到底想输出啥,既然有"xx"为啥没有"aa"
    总之大概这个意思
    kzing
        15
    kzing  
    OP
       2014-06-20 00:57:43 +08:00
    @mulog 谢谢你, 这是Ruby的一个用法, 我也刚学, 觉得这样用很酷就拿过来玩一下了. 先睡觉了.
    orzfly
        16
    orzfly  
       2014-06-20 01:04:32 +08:00   ❤️ 1
    Ruby 里也用不上 ('ab'..'xy').to_a 啊,用 [*'aa'..'zz'] 就好了~\(≧▽≦)/~啦啦啦
    glasslion
        17
    glasslion  
       2014-06-20 01:07:10 +08:00
    数学老师死的早系列
    mikale
        18
    mikale  
       2014-06-20 01:18:48 +08:00
    [x+y for x in map(chr,range(97,122)) for y in map(chr,range(97,122))]
    dreampuf
        19
    dreampuf  
       2014-06-20 02:04:59 +08:00   ❤️ 1
    os.popen("echo {a..x}{b..y}").read().split()

    [a+b for a, b in itertools.product(string.lowercase[:-2], string.lowercase[1:-1])]

    这种比较会不会只能证明 Because I can.
    Pythonic的楼上已经有了,规规矩矩的。总之要实现语言不支持的特性时,import this
    pandada8
        20
    pandada8  
       2014-06-20 08:15:07 +08:00   ❤️ 1
    import itertools
    import string
    ("".join(i) for i in itertools.product(string.ascii_lowercase, repeat=2))
    s51431980
        21
    s51431980  
       2014-06-20 09:46:09 +08:00
    当大牛花了半小时想出两行pythonic代码的时候,实习生用几分钟写了四行简明但看起来不pythonic的代码实现了相同的功能
    shyrock
        22
    shyrock  
       2014-06-20 10:11:50 +08:00
    就代码易读易理解来说,我觉得5楼的最好。而且我认为这就是优雅。
    Kabie
        23
    Kabie  
       2014-06-20 10:29:18 +08:00
    很可惜上面所有直接遍历的实现都是错的…………至少……和Ruby里的行为不同……

    这个还是朴实的做个生成器吧。。。

    当然……ruby里的这个字符串succ的行为有很多特例。。。唯一能正确实现的办法……恐怕只能是把 http://www.ruby-doc.org/core-2.1.2/String.html#method-i-succ 的代码翻译成Python了……
    glasslion
        24
    glasslion  
       2014-06-20 10:37:01 +08:00
    @shyrock 那么'asfedfger'..'rghrehtrh' 也用多重循环来写?
    generic
        25
    generic  
       2014-06-20 10:43:22 +08:00 via Android
    @Kabie 这个例子告诉我们,在X语言社区里问“Y语言的某功能在X语言里怎么实现”,最好先说明其在Y语言里的行为。
    wangtai
        26
    wangtai  
       2014-06-20 11:48:34 +08:00
    小弟不懂Ruby,请问各位Ruby大神,这种写法一般在什么场景下使用啊
    est
        27
    est  
       2014-06-20 12:02:13 +08:00   ❤️ 1
    哈哈,LZ这个卡位比较好。几个python解结果和LZ的结果不一样。
    kzing
        28
    kzing  
    OP
       2014-06-20 12:04:49 +08:00
    @generic 原来V2EX已经默认位Ptyhon社区了吗= =!
    kzing
        30
    kzing  
    OP
       2014-06-20 12:26:50 +08:00
    @generic 这不是更惨吗...那我应该会有这样的回复" 这是Ruby的板块, 你提问Python的问题?"
    hahastudio
        31
    hahastudio  
       2014-06-20 12:46:46 +08:00   ❤️ 1
    关键是LZ太欺负人= =
    不给清楚里面怎么迭代的= =
    哪知道"ax"后面是 "ay", "az", "ba", "bb" 啊= =
    这应该是从aa到zz里面掐了ab到xy这一段= =

    我给一个比较Pythonic的方案,在14L @mulog 的方案上稍微改一下就可以
    反正没有缩进,就直接在这里贴了
    用了''.join(t),这样你想涨长就改repeat和if里的边界就好了= =

    import string
    import itertools

    s = string.ascii_lowercase
    result = [ ''.join(t) for t in itertools.product(s, repeat=2) if "ab" <= ''.join(t) <= "xy" ]
    yuankui
        32
    yuankui  
       2014-06-20 13:21:44 +08:00
    写个函数吧。。
    to_a('aa','zz') rets ['aa',...,'zz']
    shyrock
        33
    shyrock  
       2014-06-20 13:23:37 +08:00
    @glasslion 不懂ruby,'asfedfger'..'rghrehtrh' 出怎样的结果?
    fwee
        34
    fwee  
       2014-06-20 13:33:00 +08:00
    @shyrock 取下一个值会调用next方法,很类似haskell,一般都是1..9这种数字范围
    binux
        35
    binux  
       2014-06-20 14:12:07 +08:00
    这个返回里面有 az 吗?如果有 az 为什么会有,不是只到 xy 吗?那有 aA,aZ 吗?
    不理解这个函数是干嘛的。
    manfay
        36
    manfay  
       2014-06-20 14:55:42 +08:00
    如果返回里有 az ,那么这个函数就是 Python 想要避免的 implicit.

    Explicit is better than implicit.
    blacktulip
        37
    blacktulip  
       2014-06-20 14:56:20 +08:00 via iPhone
    此贴好好玩,you are not your programming language. 不用觉得伤自尊。
    Kabie
        38
    Kabie  
       2014-06-20 16:07:16 +08:00
    https://github.com/topazproject/topaz/blob/master/topaz/objects/stringobject.py#L274

    String#succ 的 python 版。。。。。。其实和 C 没啥区别了。。。
    reusFork
        39
    reusFork  
       2014-06-20 16:48:40 +08:00
    jinyiming321
        40
    jinyiming321  
       2014-06-20 18:24:55 +08:00
    ruby这个是抄perl的。。。
    est
        41
    est  
       2014-06-20 18:38:09 +08:00   ❤️ 2
    @hahastudio 同意。为什么只遍历到a-z,为什么不会遍历大写A-Z?

    把LZ的语句改一下:

    ('Ww'..'xy').to_a

    那么请问Ruby为何不W X Y Z a b c ... w x 这样遍历?为什么不会xy结尾停止而是Zz停止?

    ('[a'..'xy').to_a

    为什么又只会遍历 [ 开头的,但是不会结束于[y而是[z???

    所以总结一句话:滥用语言特性,隐蔽黑魔法。LZ的“妙用”只是一个巧合。
    hahastudio
        42
    hahastudio  
       2014-06-20 19:18:58 +08:00
    @est 对,ruby的这块感觉很莫名其妙的
    大写..小写会在Z处断片

    再加几个

    >> ("aa".."ZZ").to_a
    => []
    >> ('[ab'..'xy').to_a
    => ["[ab"]
    >> ("01".."10").to_a
    => ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10"]
    >> ("a01".."z10").to_a
    => 你会看到"a99", "b00"
    >> ("01a".."10b").to_a
    => 你会看到"01z", "02a", "02b", "02c",最后是"09z", "10a", "10b"

    这种跟期待不一样的返回值还是有点伤人的

    嘛,不过是个语言都有一些坑,Python也有
    所以优雅只是相对的,对不用的语言,优雅的地方有时不一样;对同一个语言的同一种语法,有时优雅,有时就不怎么好看了
    mikale
        43
    mikale  
       2014-06-21 15:13:11 +08:00
    方法给了,还要一样,真是矫情,来一个跟题目一样的。

    [x+y for x in map(chr,range(97,121)) for y in map(chr,range(98,122))]
    yykrlc
        44
    yykrlc  
       2020-06-16 11:50:19 +08:00
    ruby 的 x = {"a": 1 "b": 2}
    y = 'b'
    > x[y]
    => nil
    > x[:b]
    => 2
    怎么解我不能传值:b 吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2575 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:30 · PVG 18:30 · LAX 02:30 · JFK 05:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.