【问题标题】:Iterate through a List Multiple times Cyclically starting from the Matching Index从匹配索引开始循环遍历列表多次
【发布时间】:2014-12-21 19:57:14
【问题描述】:

我需要在 python 中执行以下操作。我有一个字符串列表list,一个要搜索的字符串text,以及包含要打印的元素数量的变量x。我想遍历x 没有。 list 的连续元素,必要时环绕到 list 的前面。

首先,我需要在list 中找到第一个以text 作为子字符串的元素。然后,我将从list 的第一个元素开始 匹配的元素之后,并继续遍历list 的总共x 连续元素,必要时环绕。 p>

我该怎么做?

x = 11
text = "string5"
list = ["string1", "string2", "string3", "string4", "string5", "string6", "string7"]

# not sure what to do here...
for elem in list:
    if text in elem:
        #iterate through list, begin with elem and get the next 11 elements
        #once you've reached string7, start over with string1`

在本例中,我希望最终查看以下 11 个元素:

string6
string7
string1
string2
string3
string4
string5
string6
string7
string1
string2

【问题讨论】:

  • 我指的是“文本”之后的元素。对不起
  • 你使用if text in elem。是有意搜索ŧest 是否存在于elem 中,还是要比较字符串if text == elem
  • @spectras OP 现在很清楚他正在寻找一个子字符串:“列表中第一个以文本为子字符串的元素
  • 那么你的答案不仅是风格最好的答案,而且也是唯一一个真正做到了他想要做的事情。
  • 不,我不想比较字符串。我正在寻找一个子字符串。这是故意的。

标签: python list iterator cycle slice


【解决方案1】:

您可以使用cycle from itertools,也可以与isliceenumerate 结合使用。

from itertools import cycle, islice

x = 11
text = "string5"
lst = ["string1", "string2", "string3", "string4", "string5", "string6", "string7"]
for i, elem in enumerate(lst):
    if text in elem:
        next11 = list(islice(cycle(lst), i+1, i+1+x))
        print(next11)
        print(len(next11))

输出:

['string6', 'string7', 'string1', 'string2', 'string3', 'string4', 'string5', 'string6', 'string7', 'string1', 'string2']
11

【讨论】:

  • 好点使用itertools。但是,我只会使用lst.index(text) 来找出起始位置。
  • @spectras index 不起作用。他不是在测试是否相等,而是在测试 text 是否 in elem。此外,可能有多个匹配项。
  • 确实,仅考虑到他的示例,我认为使用in 而不是比较是他的代码中的错误。值得问他。如果有多个匹配,index 返回第一个。
  • 无论如何都赞成,因为这个答案是迄今为止最pythonic的一个。
【解决方案2】:

对于我们的问题数据:

x = 11 #no. of elements to get
text = 'string5' #text to search in elements of list
lst = ['string1', 'string2', 'string3', 'string4', 'string5', 'string6', 'string7'] 
n = len(lst) 

# index of required text
i = lst.index(text)

算法 1:(循环和切片)

大多数pythonic方法是使用itertools模块offcourse中的islicecycle函数:

  • 无限循环/重复列表(cycle 函数)
  • 使用重复列表中的开始/停止索引切出/选择所需元素(slice 函数)

代码:

from itertools import cycle, islice 
desired = list( islice( cycle( lst), i+1, i+1+x))

算法 2:(循环和模索引)

更传统的方式是:

  • 遍历列表x 没有。在匹配索引之后开始的时间,i+1
  • 使用modulo 索引循环遍历列表元素

代码:

desired = [ lst[ j%n] for j in range(i+1, i+1+x)] 

算法 3 - 错误的实现:(循环和重复)

许多糟糕/缓慢的实现也是可能的,例如使用numpy 函数,如rolltile

  • 滚动/旋转numpy 数组,使其从匹配索引处的元素开始,i
  • 平铺/重复数组以增加其长度超过所需的x 编号。元素数
  • 选择x 没有。元素数

代码:

def nextx(lst,i,n,x):
    ll = np.array(lst)
    rll = np.roll(ll, n-i)
    trll = np.tile(rll, x%n+1)
    return list(trll[:x])

输出:

>>> nextx(lst,5,7,11)
['string6', 'string7', 'string1', 'string2', 'string3', 'string4', 'string5', 'string6', 'string7', 'string1', 'string2']
>>> nextx(lst,5,7,11) == [lst[j%len(lst)] for j in range(5,5+11)] == list(islice(cycle(lst),5,5+11))
True

时间:

iPython 线魔术函数%timeit 显示Algorithm 1~1.5 and ~11 times faster 分别比2 和3 差一点:

>>> %timeit list( islice( cycle( lst), 5, 5+11))
100000 loops, best of 3: 1.83 µs per loop

>>> %timeit [ lst[ j%len(lst)] for j in range(5, 5+11)] 
100000 loops, best of 3: 2.76 µs per loop

>>> %timeit nextx(lst,5,7,11)
10000 loops, best of 3: 20.6 µs per loop

结论:

只要您可以使用cycleislicecountrepeat 等,使用itertools 是最快、最流畅的方式!

【讨论】:

    【解决方案3】:

    希望这会有所帮助

    >>> x = 11
    >>> text = "string5"
    >>> list = ["string1", "string2", "string3", "string4", "string5", "string6", "string7"]
    
    >>> for i in range(len(list)):
            if text in list[i]:
                a=i+1;
                break;
    
    >>> L = [list[i%len(list)] for i in range(a, a+x)]
    
    >>> L
    ['string6', 'string7', 'string1', 'string2', 'string3', 'string4', 'string5', 'string6', 'string7',     'string1', 'string2']
    

    【讨论】:

      【解决方案4】:

      annoid 没有得到它,所以这是一个漂亮的解决方案.. :P

      >>> x = 11
      >>> text = "string5"
      >>> list = ["string1", "string2", "string3", "string4", "string5", "string6", "string7"]
      >>> offset = list.index(text)
      >>> list_len = len(list)
      >>> for i in range(x):
      >>>     print(list[(i+offset)%list_len])
      

      它假定列表中的每个字符串都是唯一的,否则你可以设置偏移量。

      【讨论】:

        【解决方案5】:

        使用while循环?

        i = 0
        n = 0
        while 1:
          if i > len(list):
            i = 0
          if (k > x):
            break
          print(list[i])
          i += 1
          k += 1
        

        【讨论】:

          猜你喜欢
          • 2015-12-18
          • 1970-01-01
          • 1970-01-01
          • 2017-10-24
          • 2017-03-24
          • 1970-01-01
          • 2017-09-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多