Python将列表拆分为给定开始/结束关键字的子列表

时间:2018-02-14 09:40:36

标签: python list loops sublist

如果我有一个清单,请说

lst = ['hello', 'foo', 'test', 'world', 'bar', 'idk']

我想将其拆分为以'foo''bar'作为开始和结束关键字的子列表,以便我得到

lst = ['hello', ['foo', 'test', 'world', 'bar'], 'idk']

我目前的做法如下:

def findLoop(t):   
    inds = [index for index, item in enumerate(t) if item in ["FOO", "BAR"]]
    centre = inds[(len(inds)/2)-1:(len(inds)/2)+1]
    newCentre = t[centre[0]:centre[1]+1]
    return t[:centre[0]] + [newCentre] + t[centre[1]+1:]

def getLoops(t):
    inds = len([index for index, item in enumerate(t) if item in ["FOO", "BAR"]])
    for i in range(inds):
        t = findLoop(t)
    return t

这看起来有点混乱,但它对嵌套的开始/结束关键字非常有效,因此子列表可以在子列表中形成,但它不适用于多个开始/结束关键字不在彼此之内。嵌套并不重要,所以任何帮助都会受到赞赏。

5 个答案:

答案 0 :(得分:9)

使用切片的一种方法:

>>> lst = ['hello', 'foo', 'test', 'world', 'bar', 'idk']
>>> a=lst.index('foo')
>>> b=lst.index('bar')+1
>>> lst[a:b] = [lst[a:b]]
>>> lst
['hello', ['foo', 'test', 'world', 'bar'], 'idk']

答案 1 :(得分:7)

多次开始,结束(基于Mark Tolonen的回答)

Sub TransferValues()
    Dim myValues As Variant
    With Workbooks.Open("C://My Documents//SomeWorkbook2.xlsx") 'open and reference "source " workbook
        myValues = Application.Transpose(.Worksheets("Sheet1").Range("A1").Resize(ThisWorkbook.Worksheets.Count).Value) 'store referenced workbook "Sheet1" worksheet values in column A from row 1 down to "workbook1" (i.e. the one where the macro resides in) sheets number
        .Close False 'close referenced workbook
    End With

    Dim sht As Worksheet
    For Each sht In ThisWorkbook.Worksheets
        sht.Range("A1").Value = myValues(sht.Index)
    Next
End Sub

返回:

lst = ['hello', 'foo', 'test', 'world', 'bar', 'idk','am']
t = [('foo','test'),('world','idk')]

def sublists(lst, t):
    for start,end in t:
        a=lst.index(start)
        b=lst.index(end)+1
        lst[a:b] = [lst[a:b]]
    return lst

print(sublists(lst,t)) 

答案 2 :(得分:1)

使用切片,不支持嵌套列表:

>>> lst = ['hello', 'foo', 'test', 'world', 'bar', 'idk']
>>> start_idx = lst.index('foo')
>>> end_idx = lst.index('bar')
>>> lst[:start_idx] + [lst[start_idx:end_idx+1]] + lst[end_idx+1:]
['hello', ['foo', 'test', 'world', 'bar'], 'idk']

答案 3 :(得分:1)

一种创造性的方法是将您的列表转储到JSON字符串,在需要的地方添加[],并将您的JSON字符串解析回Python嵌套列表:

import json
lst = ['hello', 'foo', 'test', 'world', 'bar', 'idk']
start_keywords = ['world', 'foo', 'test']
end_keywords = ['bar', 'idk', 'foo']
dump = json.dumps(lst)

for k in start_keywords:
    dump = dump.replace(f'"{k}"', f'["{k}"')

for k in end_keywords:
    dump = dump.replace(f'"{k}"', f'"{k}"]')

json.loads(dump)
# ['hello', ['foo'], ['test', ['world', 'bar'], 'idk']]
json.loads(dump)[2][1][0]
# 'world'

优点是它易于遵循,它适用于任意嵌套列表,并检测结构是否正确。但是,您需要确保您的文字不包含"

答案 4 :(得分:1)

要使代码达到预期效果,您需要进行以下更改:

  1. 切片索引必须是整数。如果您的测试列表具有奇数长度,则您的findLoop函数将在第二行失败。将切片索引的类型强制转换为int以向下舍入(这里需要)

    centre = inds[int(len(inds)/2)-1:int(len(inds)/2)+1]
    
  2. in区分大小写。

    >>> 'foo' in ['FOO', 'BAR']
    False
    
  3. 在getLoops中,您只需要搜索对中的第一个元素,作为每次调用时来自一对单词的findLoops子列表。

    inds = len([index for index, item in enumerate(t) if item in ['foo']])
    
  4. Try it online!

    但是,正如您所注意到的,您的代码非常混乱,其他答案显示了如何使用list().index()来提高效果。

    如果您希望进一步查找嵌套子列表,则需要进一步说明您的行为方式。请考虑以下问题:

    • ['foo', 'bar']列入,然后['test', 'world']

      • 是否应该只在初始列表或子列表中发生子列表?
    • ['foo', 'world']列入,然后['test', 'bar']

      • 列表中不同级别的匹配应如何表现?