在checkio上又看到这么一个题,题目看似简单,而且难度设定是simple+,我以为随便就能写出来,没想到for if了一堆…[#滑稽]
"""已知一段用回车分隔的长字符串rhyme(类似一首诗的结构)和一个短字符串word,
要求去掉长字符串中的空格之后,形成一个类似字符矩阵的形式,然后在里面找到那个短字符串(忽略大小写),并输出坐标。
坐标的形式为(开始行,开始列,结束行,结束列)
"""
这里我的想法是逐行遍历,在每一行中再逐个字母遍历,如果找到word的第一个字母,就检查此字母的横向或纵向,如果和word全部匹配就返回,否则只要有一个不同直接break,继续遍历。代码如下:
def checkio(text, word):
# rhyme转换成列表
ls = text.replace(' ','').lower().split('\n')
# 存储结果
result = []
n = len(word)
for i in range(len(ls)):
for j in range(len(ls[i])):
if ls[i][j] == word[0]:
# 如果找到的字母在一行末尾,直接看列就可以
if j == len(ls[i]) - 1:
for k in range(n):
if ls[i+k][j] == word[k]:
continue
result.extend([i+1, j+1, i+n, j+1])
return result
# 否则需要行和列都看
for x in range(n):
# 在同行寻找word
if ls[i][j+x] != word[0+x]:
# 行找不到找列
for y in range(n):
if ls[i+y][j] != word[0+y]:
# 列也找不到,直接退出此次循环
break
else:
result.extend([i+1, j+1, i+n, j+1])
return result
break
else:
result.extend([i+1, j+1, i+1, j+n])
return result
j += 1
i += 1
一个simple+的题目被我写成这样,难受啊。于是看了别的小伙伴的作业,确实有一些很厉害的,比如这个:
from itertools import zip_longest
def checkio(text, word):
horizontal = text.lower().replace(' ', '').splitlines()
for i, row in enumerate(horizontal, 1):
index = row.find(word)
if index >= 0:
return [i, index+1, i, index+len(word)]
vertical = [''.join(line) for line in zip_longest(*horizontal, fillvalue='-')]
for i, col in enumerate(vertical, 1):
index = col.find(word)
if index >= 0:
return [index+1, i, index+len(word), i]
这段代码真的厉害,我是逐个字母对比,而他是直接find word。值得注意的是,这段代码引用了一个zip_longest()函数,这是个什么函数呢?
我们都知道zip()函数,zip([seq1, …])接受一系列可迭代对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。若传入参数的长度不等,则返回列表的长度和参数中长度最短的对象相同。
>>> ls1 = ['a', 'b', 'c']
>>> ls2 = [1, 2, 3]
>>> print(zip(ls1, ls2))
<zip object at 0x0530BC88>
>>> print(list(zip(ls1, ls2)))
[('a', 1), ('b', 2), ('c', 3)]
>>> ls3 = ['A', 'B']
>>> print(list(zip(ls1, ls3)))
[('a', 'A'), ('b', 'B')]
这个函数需要导入itertools模块,和zip()函数功能类似,区别在于zip()函数在两个参数长度不等时,返回列表的长度与较短的对象保持一致;而zip_longest则与较长的对象保持一致。对于不足的部分默认用None补齐,但是可以使用fillvalue参数来指定。
>>> from itertools import zip_longest
>>> ls1 = ['a', 'b', 'c', 'd']
>>> ls2 = [1,2,3]
>>> print(list(zip_longest(ls1, ls2)))
[('a', 1), ('b', 2), ('c', 3), ('d', None)]
>>> print(list(zip_longest(ls1, ls2, fillvalue='马拉卡')))
[('a', 1), ('b', 2), ('c', 3), ('d', '马拉卡')]
这道题如果用常规方法确实比较麻烦,看着简单,却要逐个遍历确定。如果直接查找整个word会快很多,但用这种思路,水平方向还好,垂直方向很难连成一个词,这就要用到zip_longest()函数。通过这次的学习,了解了一个新的第三方函数,以后应该还会用到。