اجتياز القائمة بترتيب عكسي في بايثون
سؤال
لذلك أستطيع أن أبدأ من len(collection)
وتنتهي في collection[0]
.
يحرر:عذرًا، نسيت أن أذكر أنني أريد أيضًا أن أتمكن من الوصول إلى فهرس الحلقة.
المحلول
استخدم المدمج في reversed()
وظيفة:
>>> a = ["foo", "bar", "baz"]
>>> for i in reversed(a):
... print(i)
...
baz
bar
foo
لوصول أيضا مؤشر الأصلي، استخدم enumerate()
في القائمة الخاصة بك قبل تمرير لreversed()
:
>>> for i, e in reversed(list(enumerate(a))):
... print(i, e)
...
2 baz
1 bar
0 foo
ومنذ enumerate()
يعود مولد ولا يمكن عكس المولدات الكهربائية، تحتاج إلى تحويله إلى list
أولا.
نصائح أخرى
ويمكنك القيام به:
for item in my_list[::-1]:
print item
و(أو ما تريد أن تفعل في لحلقة).
وشريحة [::-1]
عكس القائمة في لحلقة (ولكن لن تعدل في الواقع قائمتك "بشكل دائم").
إذا كنت في حاجة إلى مؤشر حلقة، ولا تريد أن تجتاز قائمة كاملة مرتين، أو استخدام ذاكرة إضافية، كنت أكتب مولد.
def reverse_enum(L):
for index in reversed(xrange(len(L))):
yield index, L[index]
L = ['foo', 'bar', 'bas']
for index, item in reverse_enum(L):
print index, item
ويمكن ان يتم ذلك كما يلي:
for i in range(len(collection)-1, -1, -1): print collection[i] # print(collection[i]) for python 3. +
وهكذا تخمين كان جدا قريب :) محرجا قليلا لكنها ما يقول أساسا: عرض من 1 أقل من len(collection)
، والحفاظ على الذهاب حتى تحصل على قبل -1، من خلال خطوات -1.
ولمعلوماتك، وظيفة help
مفيد جدا لأنه يتيح لك عرض مستندات عن شيء من وحدة بيثون، على سبيل المثال:
وhelp(range)
وظيفة مدمج reversed
هو مفيد:
for item in reversed(sequence):
الوثائق للحصول على عكس ما يفسر حدودها.
لفي الحالات التي لا بد لي من السير في الاتجاه المعاكس تسلسل جنبا إلى جنب مع مؤشر (على سبيل المثال، لإجراء تعديلات في مكان تغيير طول تسلسل)، ولقد عرفت هذه الوظيفة وحدة بلدي codeutil:
import itertools
def reversed_enumerate(sequence):
return itertools.izip(
reversed(xrange(len(sequence))),
reversed(sequence),
)
وهذا واحد يتجنب إنشاء نسخة من التسلسل. ومن الواضح أن القيود reversed
لا تزال سارية.
>>> l = ["a","b","c","d"]
>>> l.reverse()
>>> l
['d', 'c', 'b', 'a']
وOR
>>> print l[::-1]
['d', 'c', 'b', 'a']
وماذا عن دون إعادة قائمة جديدة، يمكنك القيام به من خلال الفهرسة:
>>> foo = ['1a','2b','3c','4d']
>>> for i in range(len(foo)):
... print foo[-(i+1)]
...
4d
3c
2b
1a
>>>
وOR
>>> length = len(foo)
>>> for i in range(length):
... print foo[length-i-1]
...
4d
3c
2b
1a
>>>
وأنا أحب نهج مولد واحد بطانة:
((i, sequence[i]) for i in reversed(xrange(len(sequence))))
وأيضا، هل يمكن استخدام إما "مجموعة" أو وظائف "العد". كما يلي:
a = ["foo", "bar", "baz"]
for i in range(len(a)-1, -1, -1):
print(i, a[i])
3 baz
2 bar
1 foo
ويمكنك أيضا استخدام "عدد" من itertools على النحو التالي:
a = ["foo", "bar", "baz"]
from itertools import count, takewhile
def larger_than_0(x):
return x > 0
for x in takewhile(larger_than_0, count(3, -1)):
print(x, a[x-1])
3 baz
2 bar
1 foo
استخدم list.reverse()
ثم تكرار كما تفعل عادة.
def reverse(spam):
k = []
for i in spam:
k.insert(0,i)
return "".join(k)
وعن أي وقت مضى ما يستحق يمكنك أن تفعل ذلك مثل هذا أيضا. بسيطة جدا.
a = [1, 2, 3, 4, 5, 6, 7]
for x in xrange(len(a)):
x += 1
print a[-x]
إذا كنت في حاجة إلى المؤشر قائمتك صغيرة، فإن الطريقة الأكثر قراءة هو أن تفعل reversed(list(enumerate(your_list)))
مثل الجواب المقبول تقول. ولكن هذا يخلق نسخة من القائمة الخاصة بك، حتى إذا قائمتك يأخذ حيزا كبيرا من الذاكرة الخاصة بك سيكون لديك لطرح مؤشر إرجاعها بواسطة enumerate(reversed())
من len()-1
.
إذا كنت بحاجة فقط للقيام بذلك مرة واحدة:
a = ['b', 'd', 'c', 'a']
for index, value in enumerate(reversed(a)):
index = len(a)-1 - index
do_something(index, value)
وأو إذا كنت تحتاج إلى القيام بذلك عدة مرات يجب عليك استخدام مولد:
def enumerate_reversed(lyst):
for index, value in enumerate(reversed(lyst)):
index = len(lyst)-1 - index
yield index, value
for index, value in enumerate_reversed(a):
do_something(index, value)
وظيفة العكس تأتي في متناول اليدين هنا:
myArray = [1,2,3,4]
myArray.reverse()
for x in myArray:
print x
الإجابات الأخرى جيدة، ولكن إذا كنت تريد أن تفعل ذلكقائمة أسلوب الفهم
collection = ['a','b','c']
[item for item in reversed( collection ) ]
واستخدام المدمج في وظيفة reversed()
لكائن تسلسل، وهذا الأسلوب له تأثير كل تسلسل
ويمكنك أيضا استخدام حلقة while
:
i = len(collection)-1
while i>=0:
value = collection[i]
index = i
i-=1
ويمكنك استخدام مؤشر سلبي في عادية للحلقة:
>>> collection = ["ham", "spam", "eggs", "baked beans"]
>>> for i in range(1, len(collection) + 1):
... print(collection[-i])
...
baked beans
eggs
spam
ham
لوصول المؤشر كما لو كنت بالتكرار إلى الأمام على نسخة عكس من جمع واستخدام i - 1
:
>>> for i in range(1, len(collection) + 1):
... print(i-1, collection[-i])
...
0 baked beans
1 eggs
2 spam
3 ham
لوصول الأصلي، مؤشر الامم المتحدة وعكسه، واستخدام len(collection) - i
:
>>> for i in range(1, len(collection) + 1):
... print(len(collection)-i, collection[-i])
...
3 baked beans
2 eggs
1 spam
0 ham
ووسيلة معبرة لتحقيق reverse(enumerate(collection))
في بيثون 3:
zip(reversed(range(len(collection))), reversed(collection))
وفي بيثون 2:
izip(reversed(xrange(len(collection))), reversed(collection))
ولست متأكدا من السبب في أننا لم يكن لديك اختصار لهذا، على سبيل المثال:
def reversed_enumerate(collection):
return zip(reversed(range(len(collection))), reversed(collection))
وأو لماذا ليس لدينا reversed_range()
ونهج مع عدم وجود واردات:
for i in range(1,len(arr)+1):
print(arr[-i])
أو
for i in arr[::-1]:
print(i)
لاستخدام المؤشرات السلبية: تبدأ في -1 وخطوة إلى الوراء -1 في كل التكرار
>>> a = ["foo", "bar", "baz"]
>>> for i in range(-1, -1*(len(a)+1), -1):
... print i, a[i]
...
-1 baz
-2 bar
-3 foo
وهناك طريقة بسيطة:
n = int(input())
arr = list(map(int, input().split()))
for i in reversed(range(0, n)):
print("%d %d" %(i, arr[i]))
input_list = ['foo','bar','baz']
for i in range(-1,-len(input_list)-1,-1)
print(input_list[i])
وأعتقد أن هذا واحد هو أيضا طريقة بسيطة للقيام بذلك ... قراءة من نهاية والحفاظ على decrementing حتى طول قائمة، لأننا أبدا تنفيذ "نهاية" مؤشر بالتالي بإضافة -1 أيضا
وإذا افترضنا هو العثور على العنصر الأخير الذي يرضي بعض شرط في قائمة (أي أولا عند النظر الى الوراء)، وأنا اتلقى الأرقام التالية:
>>> min(timeit.repeat('for i in xrange(len(xs)-1,-1,-1):\n if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
4.6937971115112305
>>> min(timeit.repeat('for i in reversed(xrange(0, len(xs))):\n if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
4.809093952178955
>>> min(timeit.repeat('for i, x in enumerate(reversed(xs), 1):\n if 128 == x: break', setup='xs, n = range(256), 0', repeat=8))
4.931743860244751
>>> min(timeit.repeat('for i, x in enumerate(xs[::-1]):\n if 128 == x: break', setup='xs, n = range(256), 0', repeat=8))
5.548468112945557
>>> min(timeit.repeat('for i in xrange(len(xs), 0, -1):\n if 128 == xs[i - 1]: break', setup='xs, n = range(256), 0', repeat=8))
6.286104917526245
>>> min(timeit.repeat('i = len(xs)\nwhile 0 < i:\n i -= 1\n if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
8.384078979492188
وهكذا، أبشع الخيار xrange(len(xs)-1,-1,-1)
هو الأسرع.
إذا كنت لا تمانع في مؤشر يجري سلبي، يمكنك القيام به:
>>> a = ["foo", "bar", "baz"]
>>> for i in range(len(a)):
... print(~i, a[~i]))
-1 baz
-2 bar
-3 foo
وأعتقد أن الطريقة الأكثر أناقة هو تحويل enumerate
وreversed
باستخدام مولد التالي
(-(ri+1), val) for ri, val in enumerate(reversed(foo))
والذي يولد على عكس مكرر enumerate
مثال:
foo = [1,2,3]
bar = [3,6,9]
[
bar[i] - val
for i, val in ((-(ri+1), val) for ri, val in enumerate(reversed(foo)))
]
والنتيجة:
[6, 4, 2]