Python:获取列表中两个已知项之间的项

5
我正在寻找一种方法来获取Python列表中在两个元素之间的所有项。算法必须遍历整个数组。
例如:
我有一个字符串如"Mo-Fr",我想最终得到一个列表: [Monday, Tuesday, Wednesday, Thursday, Friday] 但我也希望以这种方式工作: string = "Fr-Mo" list = Friday, Saturday, Sunday, Monday 我的代码目前看起来像这样:
string = 'Mo-Fr'
days_order = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
days_dict = {'Mo' : 'Montag',
             'Di' : 'Dienstag',
             'Mi' : 'Mittwoch',
             'Do' : 'Donnerstag',
             'Fr' : 'Freitag',
             'Sa' : 'Samstag',
             'So' : 'Sonntag',}
days = string.split('-')
days = [days_order.index(day) for day in days]
days_list = [days_dict[day] for day in days_order if    days_order.index(day) in range(days[0], days[1] + 1)]

如果字符串看起来像“Mo-Fr”,那么我的代码就可以正常工作,但是当字符串为“Fr-Mo”时,代码当然不能正常工作。有什么好的方法可以干净利落地解决这个问题吗?

谢谢!


这可能是一个使用传统的while循环最简洁的解决方案的场合。 - Obversity
1
你可以将每天的订单存储为整数0-6,这样你就能够进行比较和重新排序。 - cafebabe1991
2
使用模块运算符获取一个限制在0-6之间的序列。以下代码:for i in range(10): print i%7 会产生以下输出:0 1 2 3 4 5 6 0 1 2 3 ... - David Lemon
4个回答

3

一个简单的方法是使用两份 days_order 列表,然后用两个步骤来切片该列表。

days_order = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
days_dict = {
    'Mo' : 'Montag',
    'Di' : 'Dienstag',
    'Mi' : 'Mittwoch',
    'Do' : 'Donnerstag',
    'Fr' : 'Freitag',
    'Sa' : 'Samstag',
    'So' : 'Sonntag',
}

def daylist(days):
    first, last = days.split('-')

    days = days_order * 2
    i = days.index(first)
    days = days[i:]

    i = days.index(last)
    days = days[:i+1]
    return [days_dict[s] for s in days]

s = "Mo-Fr"
print s, daylist(s)

s = "Fr-Mo"
print s, daylist(s)

输出

Mo-Fr ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag']
Fr-Mo ['Freitag', 'Samstag', 'Sonntag', 'Montag']

如果两个给定的项目是相同的,上面的代码只返回单个日期。如果希望在这种情况下返回整个一周的日期,则可以使用ekhumoro的算法。

这是我的版本:

days_order = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
days_dict = {
    'Mo' : 'Montag',
    'Di' : 'Dienstag',
    'Mi' : 'Mittwoch',
    'Do' : 'Donnerstag',
    'Fr' : 'Freitag',
    'Sa' : 'Samstag',
    'So' : 'Sonntag',
}

def daylist(days):
    first, last = days.split('-')

    days = days_order * 2
    i = days.index(first)
    j = days.index(last, i + 1)
    return [days_dict[s] for s in days[i:j+1]]    

s = "Mo-Fr"
print s, daylist(s)

s = "Fr-Mo"
print s, daylist(s)

s = "Di-Di"
print s, daylist(s)

s = "Do-Mi"
print s, daylist(s)

输出

Mo-Fr ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag']
Fr-Mo ['Freitag', 'Samstag', 'Sonntag', 'Montag']
Di-Di ['Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag', 'Montag', 'Dienstag']
Do-Mi ['Donnerstag', 'Freitag', 'Samstag', 'Sonntag', 'Montag', 'Dienstag', 'Mittwoch']

这里介绍另一种方法,这次使用模算术,正如David Lemon在评论中建议的那样:
days_short = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
days_long = [
    'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 
    'Freitag', 'Samstag', 'Sonntag'
]

def daylist(days):
    first, last = days.split('-')

    i = days_short.index(first)
    j = days_short.index(last)
    if j <= i:
        j += 7

    return [days_long[k % 7] for k in range(i, j+1)]

s = "Mo-Fr"
print s, daylist(s)

s = "Fr-Mo"
print s, daylist(s)

s = "Di-Di"
print s, daylist(s)

s = "Do-Mi"
print s, daylist(s)

感谢您基于我的代码提供了这个详细的示例!运行得非常好!而且易于理解。 - Sonic
@rebeling:Sonic在问题中没有提到当两个给定的日期相同时需要完整的一天循环。但我会在我的答案中添加更多代码。 - PM 2Ring
是的,David Lemons 的方法相当干净。 - rebeling

3
一个简单的解决方案是将 days_order 列表翻倍,以包含所有工作日的旋转排列:
>>> days_order = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'] * 2

然后像这样获取起始/结束索引:
>>> string = 'Fr-Mo'
>>> days = string.split('-')
>>> start = days_order.index(days[0])
>>> end = days_order.index(days[1], start + 1) + 1

最后按照以下方式构建天数列表:
>>> [days_dict[day] for day in days_order[start:end]]
['Freitag', 'Samstag', 'Sonntag', 'Montag']

这就是我24分钟前说的。:) 尽管如此,我正在对一个切片列表执行第二个索引步骤,而不是提供起始索引。 - PM 2Ring
谢谢你根据我的示例提供的答案...它很好地运行了。 - Sonic
这是这里唯一可用于“滴滴”的解决方案 - 做得好。 - rebeling

1
这里有一个相关的函数:

function for this:

def AtoB (string, lst):
    a, b = string.split("-")
    sublist = []
    i = lst.index(a)
    while lst[i] != b:
        sublist.append(lst[i])
        i+=1
        i%=len(lst)
    return sublist + [b]

使用方法如下:
days = AtoB(string, days_order)

0

只需循环一次days_order:

for from_to in ['Di-Sa', 'Fr-Mi', 'Di-Di']:

    start_matched, collect_for_buffer = False, True
    head, buffer, tail = [], [], []
    _from, _to = from_to[-2:], from_to[:2]

    for x in days_order:

        if _from == x:
            tail.append(days_dict[x])
            if start_matched is False:
                tail = buffer + tail
            start_matched = False

        else:
            if start_matched is False and collect_for_buffer:
                buffer.append(days_dict[x])

        if _to == x or start_matched:
            start_matched = True
            head.append(days_dict[x])

    print from_to, head + tail

就这样

Di-Sa ['Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag']
Fr-Mi ['Freitag', 'Samstag', 'Sonntag', 'Montag', 'Dienstag', 'Mittwoch']
Di-Di ['Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag', 'Montag', 'Dienstag']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接