我怎么能在python中做这样的事情?
foo = somevalue
previous = next = 0
for (i=1; i<objects.length(); i++) {
if (objects[i]==foo){
previous = objects[i-1]
next = objects[i+1]
}
}
答案 0 :(得分:120)
直到现在,解决方案只处理列表,而且大多数都在复制列表。根据我的经验,很多时候这是不可能的。
此外,他们没有处理您可以在列表中重复元素的事实。
你问题的标题是“循环中的上一个和下一个值”,但是如果你在循环中运行大多数答案,你最终会在每个循环上再次迭代整个列表找到它的元素。
所以我刚刚创建了一个函数。使用itertools
模块,拆分并切片iterable,并生成包含前一个和下一个元素的元组。不完全是你的代码所做的,但值得一看,因为它可能解决你的问题。
from itertools import tee, islice, chain, izip
def previous_and_next(some_iterable):
prevs, items, nexts = tee(some_iterable, 3)
prevs = chain([None], prevs)
nexts = chain(islice(nexts, 1, None), [None])
return izip(prevs, items, nexts)
然后在循环中使用它,你将在其中包含上一个和下一个项目:
mylist = ['banana', 'orange', 'apple', 'kiwi', 'tomato']
for previous, item, nxt in previous_and_next(mylist):
print "Item is now", item, "next is", nxt, "previous is", previous
结果:
Item is now banana next is orange previous is None
Item is now orange next is apple previous is banana
Item is now apple next is kiwi previous is orange
Item is now kiwi next is tomato previous is apple
Item is now tomato next is None previous is kiwi
它适用于任何大小的列表(因为它不会复制列表),以及任何可迭代的(文件,集等)。这样您就可以遍历序列,并在循环内部使用上一个和下一个项目。无需再次搜索序列中的项目。
代码的简短说明:
tee
用于在输入序列chain
将两个序列连接成一个;它用于将单元素序列[None]
附加到prevs
islice
用于制作除第一个元素之外的所有元素的序列,然后使用chain
将None
附加到其末尾some_iterable
的独立序列,如下所示:
prevs
:None, A, B, C, D, E
items
:A, B, C, D, E
nexts
:B, C, D, E, None
izip
用于将3个序列更改为一个三元组序列。注意izip
在任何输入序列耗尽时停止,因此prevs
的最后一个元素将被忽略,这是正确的 - 没有这样的元素,最后一个元素将是它的{{1 }}。我们可以尝试从prev
剥离最后一个元素,但prevs
的行为会使这个元素变得多余
另请注意,izip
,tee
,izip
和islice
来自chain
模块;它们在运行时(懒惰地)对它们的输入序列进行操作,这使它们变得高效,并且不需要在任何时间将整个序列同时存储在存储器中。
在itertools
中,导入python 3
时会显示错误,您可以使用izip
代替zip
。无需导入izip
,它已在zip
- source
答案 1 :(得分:76)
这应该可以解决问题。
foo = somevalue
previous = next_ = None
l = len(objects)
for index, obj in enumerate(objects):
if obj == foo:
if index > 0:
previous = objects[index - 1]
if index < (l - 1):
next_ = objects[index + 1]
以下是enumerate
函数的文档。
答案 2 :(得分:5)
使用列表推导,返回包含当前,上一个和下一个元素的3元组:
three_tuple = [(current,
my_list[idx - 1] if idx >= 1 else None,
my_list[idx + 1] if idx < len(my_list) - 1 else None) for idx, current in enumerate(my_list)]
答案 3 :(得分:2)
这是使用没有边界错误的生成器的版本:
def trios(input):
input = iter(input) # make sure input is an iterator
try:
prev, current = input.next(), input.next()
except StopIteration:
return
for next in input:
yield prev, current, next
prev, current = current, next
def find_prev_next(objects, foo):
prev, next = 0, 0
for temp_prev, current, temp_next in trios(objects):
if current == foo:
prev, next = temp_prev, temp_next
return prev, next
print find_prev_next(range(10), 1)
print find_prev_next(range(10), 0)
print find_prev_next(range(10), 10)
print find_prev_next(range(0), 10)
print find_prev_next(range(1), 10)
print find_prev_next(range(2), 10)
请注意,边界行为是我们从不在第一个或最后一个元素中查找“foo”,这与您的代码不同。同样,边界语义很奇怪......很难从你的代码中得到解决:)
答案 4 :(得分:1)
使用条件表达式来简化python&gt; = 2.5
def prenext(l,v) :
i=l.index(v)
return l[i-1] if i>0 else None,l[i+1] if i<len(l)-1 else None
# example
x=range(10)
prenext(x,3)
>>> (2,4)
prenext(x,0)
>>> (None,2)
prenext(x,9)
>>> (8,None)
答案 5 :(得分:1)
对于任何想要解决此问题且又想循环元素的人,下面的方法都可以工作-
from collections import deque
foo = ['A', 'B', 'C', 'D']
def prev_and_next(input_list):
CURRENT = input_list
PREV = deque(input_list)
PREV.rotate(-1)
PREV = list(PREV)
NEXT = deque(input_list)
NEXT.rotate(1)
NEXT = list(NEXT)
return zip(PREV, CURRENT, NEXT)
for previous_, current_, next_ in prev_and_next(foo):
print(previous_, current_, next)
答案 6 :(得分:1)
我不知道怎么回事,因为它仅使用内置函数并且可以轻松扩展到其他偏移量:
values = [1, 2, 3, 4]
offsets = [None] + values[:-1], values, values[1:] + [None]
for value in list(zip(*offsets)):
print(value) # (previous, current, next)
(None, 1, 2)
(1, 2, 3)
(2, 3, 4)
(3, 4, None)
答案 7 :(得分:1)
两个简单的解决方案:
alist = ['Zero', 'One', 'Two', 'Three', 'Four', 'Five']
prev = alist[0]
curr = alist[1]
for nxt in alist[2:]:
print(f'prev: {prev}, curr: {curr}, next: {nxt}')
prev = curr
curr = nxt
Output[1]:
prev: Zero, curr: One, next: Two
prev: One, curr: Two, next: Three
prev: Two, curr: Three, next: Four
prev: Three, curr: Four, next: Five
alist = ['Zero', 'One', 'Two', 'Three', 'Four', 'Five']
prev = None
curr = alist[0]
for nxt in alist[1:] + [None]:
print(f'prev: {prev}, curr: {curr}, next: {nxt}')
prev = curr
curr = nxt
Output[2]:
prev: None, curr: Zero, next: One
prev: Zero, curr: One, next: Two
prev: One, curr: Two, next: Three
prev: Two, curr: Three, next: Four
prev: Three, curr: Four, next: Five
prev: Four, curr: Five, next: None
答案 8 :(得分:1)
如果您只想迭代具有下一个和上一个元素的元素(例如,您想跳过第一个和最后一个元素)并且您的输入是一个列表,您可以{{ 3}} 输入本身没有第一个元素和第二个元素:
words = "one two three four five".split()
for prev, current, nxt in zip(words, words[1:], words[2:]):
print(prev, current, nxt)
输出:
one two three
two three four
three four five
如果您不想跳过第一个和最后一个元素,并且希望在第一个元素上时将 prev
设置为 None
(并且 nxt
为None
表示最后一个元素),首先用这些值填充您的列表:
words = "one two three four five".split()
padded_words = [None, *words, None]
for prev, current, nxt in zip(padded_words, padded_words[1:], padded_words[2:]):
print(prev, current, nxt)
输出:
None one two
one two three
two three four
three four five
four five None
你可以用任何你想要的东西来填充。如果您希望您的列表“环绕”(例如,第一个元素的 prev
是最后一个元素,最后一个元素的 nxt
是第一个元素),请使用这些填充您的输入而不是None
:
# avoid IndexError if words is an empty list
padded_words = [words[-1], *words, words[0]] if words else []
输出:
five one two
one two three
two three four
three four five
four five one
答案 9 :(得分:0)
您可以在列表中使用index
查找somevalue
的位置,然后根据需要获取上一个和下一个:
def find_prev_next(elem, elements):
previous, next = None, None
index = elements.index(elem)
if index > 0:
previous = elements[index -1]
if index < (len(elements)-1):
next = elements[index +1]
return previous, next
foo = 'three'
list = ['one','two','three', 'four', 'five']
previous, next = find_prev_next(foo, list)
print previous # should print 'two'
print next # should print 'four'
答案 10 :(得分:0)
AFAIK这应该很快,但我没有测试它:
def iterate_prv_nxt(my_list):
prv, cur, nxt = None, iter(my_list), iter(my_list)
next(nxt, None)
while True:
try:
if prv:
yield next(prv), next(cur), next(nxt, None)
else:
yield None, next(cur), next(nxt, None)
prv = iter(my_list)
except StopIteration:
break
使用示例:
>>> my_list = ['a', 'b', 'c']
>>> for prv, cur, nxt in iterate_prv_nxt(my_list):
... print prv, cur, nxt
...
None a b
a b c
b c None
答案 11 :(得分:0)
使用生成器,这很简单:
signal = ['→Signal value←']
def pniter( iter, signal=signal ):
iA = iB = signal
for iC in iter:
if iB is signal:
iB = iC
continue
else:
yield iA, iB, iC
iA = iB
iB = iC
iC = signal
yield iA, iB, iC
if __name__ == '__main__':
print('test 1:')
for a, b, c in pniter( range( 10 )):
print( a, b, c )
print('\ntest 2:')
for a, b, c in pniter([ 20, 30, 40, 50, 60, 70, 80 ]):
print( a, b, c )
print('\ntest 3:')
cam = { 1: 30, 2: 40, 10: 9, -5: 36 }
for a, b, c in pniter( cam ):
print( a, b, c )
for a, b, c in pniter( cam ):
print( a, a if a is signal else cam[ a ], b, b if b is signal else cam[ b ], c, c if c is signal else cam[ c ])
print('\ntest 4:')
for a, b, c in pniter([ 20, 30, None, 50, 60, 70, 80 ]):
print( a, b, c )
print('\ntest 5:')
for a, b, c in pniter([ 20, 30, None, 50, 60, 70, 80 ], ['sig']):
print( a, b, c )
print('\ntest 6:')
for a, b, c in pniter([ 20, ['→Signal value←'], None, '→Signal value←', 60, 70, 80 ], signal ):
print( a, b, c )
请注意,包含None且与信号值相同的值的测试仍然有效,因为对信号值的检查使用“ is”,并且信号是Python不进行内插的值。不过,任何单例标记值都可以用作信号,这在某些情况下可以简化用户代码。
答案 12 :(得分:0)
我认为这可行且不复杂
array= [1,5,6,6,3,2]
for i in range(0,len(array)):
Current = array[i]
Next = array[i+1]
Prev = array[i-1]
答案 13 :(得分:0)
非常C / C ++风格的解决方案:
foo = 5
objectsList = [3, 6, 5, 9, 10]
prev = nex = 0
currentIndex = 0
indexHigher = len(objectsList)-1 #control the higher limit of list
found = False
prevFound = False
nexFound = False
#main logic:
for currentValue in objectsList: #getting each value of list
if currentValue == foo:
found = True
if currentIndex > 0: #check if target value is in the first position
prevFound = True
prev = objectsList[currentIndex-1]
if currentIndex < indexHigher: #check if target value is in the last position
nexFound = True
nex = objectsList[currentIndex+1]
break #I am considering that target value only exist 1 time in the list
currentIndex+=1
if found:
print("Value %s found" % foo)
if prevFound:
print("Previous Value: ", prev)
else:
print("Previous Value: Target value is in the first position of list.")
if nexFound:
print("Next Value: ", nex)
else:
print("Next Value: Target value is in the last position of list.")
else:
print("Target value does not exist in the list.")
答案 14 :(得分:-1)
Pythonic和优雅的方式:
objects = [1, 2, 3, 4, 5]
value = 3
if value in objects:
index = objects.index(value)
previous_value = objects[index-1]
next_value = objects[index+1] if index + 1 < len(objects) else None