如何在Python中使用字母表创建循环迭代器?

时间:2017-12-11 19:00:23

标签: python

鉴于以下情况:

import string

UPPERCASE_ALPHABET = list(string.ascii_uppercase)
LOWERCASE_ALPHABET = list(string.ascii_lowercase)

如何在跳过N个位置的字母表上创建一个循环循环?

示例1

= a, = 5

结果:f

示例2

信件 = z, = 5

结果:e

到目前为止,我得到了:

import string

UPPERCASE_ALPHABET = list(string.ascii_uppercase)
LOWERCASE_ALPHABET = list(string.ascii_lowercase)

def forward(letter, jump):
    alphabet = LOWERCASE_ALPHABET if letter.islower() else UPPERCASE_ALPHABET
    index = alphabet.index(letter)
    count = 0
    while True:
        if count == jump:
            return alphabet[index]

        if index == len(alphabet):            
            index = 0

        index += 1
        count += 1

print forward('a', 5)
print forward('z', 5)

但它看起来根本不是Pythonic ......

有更好的Pythonic方法吗?也许使用chr(ord('N')+位置)?

3 个答案:

答案 0 :(得分:1)

我编写了一个自定义迭代器类来封装itertools.cycle()并提供skip()功能,例如:

import itertools

class CyclicSkipIterator(object):

    def __init__(self, iterable):
        self._iterator = itertools.cycle(iterable)

    def __iter__(self):
        return self

    def next(self):  # use __next__ on Python 3.x
        return next(self._iterator)

    def skip(self, number=1):
        for i in xrange(number):  # use range() on Python 3.x
            next(self._iterator)

然后你可以用它完成你想要的东西:

import string

LOWERCASE_ALPHABET = list(string.ascii_lowercase)

lower_iter = CyclicSkipIterator(LOWERCASE_ALPHABET)
print(next(lower_iter))  # a
lower_iter.skip(4)  # skip next 4 letters: b, c, d, e
print(next(lower_iter))  # f
lower_iter.skip(19)  # skip another 19 letters to arrive at z
print(next(lower_iter))  # z
lower_iter.skip(4)  # skip next 4 letters: a, b, c, d
print(next(lower_iter))  # e

如果您愿意,可以添加更多功能,例如反转,迭代中迭代等等。

更新:如果您想跳转到列表中的特定元素,可以为CyclicSkipIterator添加一个方法:

class CyclicSkipIterator(object):

    def __init__(self, iterable):
        self._iterator = itertools.cycle(iterable)

    def __iter__(self):
        return self

    def __next__(self):  # use __next__ on Python 3.x
        return next(self._iterator)

    def skip(self, number=1):
        for _ in range(number):  # use range() on Python 3.x
            next(self._iterator)

    def skip_to(self, element, max_count=100):  # max_count protects against endless cycling
        max_count = max(1, max_count)  # ensure at least one iteration
        for _ in range(max_count):  # use range() on Python 3.x
            e = next(self._iterator)
            if element == e:
                break

然后你可以跳过任何你想要的字母:

import string

LOWERCASE_ALPHABET = list(string.ascii_lowercase)

lower_iter = CyclicSkipIterator(LOWERCASE_ALPHABET)
print(next(lower_iter))  # a
lower_iter.skip(4)  # skip 4 letters: b, c, d, e
print(next(lower_iter))  # f
lower_iter.skip_to("y")  # skip all letters up to y
print(next(lower_iter))  # z
lower_iter.skip(4)  # skip 4 letters: a, b, c, d
print(next(lower_iter))  # e

答案 1 :(得分:1)

我认为您对ordchr

有正确的想法
import string

def forward(letter, jump):
    if letter.islower():
        start_character = ord('a')
    else:
        start_character = ord('A')
    start = ord(letter) - start_character
    offset = ((start + jump) % 26) + start_character
    result = chr(offset)
    return result

print forward('a', 5)
print forward('z', 5)
print forward('z', 1)
print forward('a', 26)
print forward('A', 5)
print forward('Z', 5)
print forward('Z', 1)
print forward('A', 26)

<强>输出

f
e
a
a
F
E
A
A

答案 2 :(得分:0)

class CyclicIterator:
    def __init__(self,lst):
        self.lst=lst
        self.i=0
    def __iter__(self):
        return self
    def __next__(self):
        result=self.lst[self.i % len(self.lst)]
        self.i+=3   #increasing by 3
        return result
具有 iter ()和 next ()的

类符合迭代器协议。创建此迭代器类的实例

iter_cycle=CyclicIterator('abcdefghiijklmnnoprstuvyz')

numbers=range(1,27,3) # 26 letters increases by 3
list(zip(list(numbers),iter_cycle))

enter image description here