473,549 Members | 2,247 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Accessing next/prev element while for looping

When I first came to Python I did a lot of C style loops like this:

for i in range(len(myarr ay)):
print myarray[i]

Obviously the more pythonic way is:

for i in my array:
print i

The python way is much more succinct. But a lot of times I'll be looping
through something, and if a certain condition is met, need to access the
previous or the next element in the array before continuing iterating. I
don't see any elegant way to do this other than to switch back to the C
style loop and refer to myarray[i-1] and myarray[i+1], which seems
incredibly silly given that python lists under the hood are linked
lists, presumably having previous/next pointers although I haven't
looked at the interpeter source.

I could also enumerate:

for i, j in enumerate(myarr ay):
print myarray[i], j # Prints each element twice

And this way I can keep referring to j instead of myarray[i], but I'm
still forced to use myarray[i-1] and myarray[i+1] to refer to the
previous and next elements. Being able to do j.prev, j.next seems more
intuitive.

Is there some other builtin somewhere that provides better functionality
that I'm missing?
Dec 18 '05 #1
13 14709
Joseph Garvin <k0*****@kzoo.e du> wrote:
When I first came to Python I did a lot of C style loops like this:

for i in range(len(myarr ay)):
print myarray[i]

Obviously the more pythonic way is:

for i in my array:
print i

The python way is much more succinct. But a lot of times I'll be looping
through something, and if a certain condition is met, need to access the
previous or the next element in the array before continuing iterating. I
don't see any elegant way to do this other than to switch back to the C
style loop and refer to myarray[i-1] and myarray[i+1], which seems
incredibly silly given that python lists under the hood are linked
lists, presumably having previous/next pointers although I haven't
looked at the interpeter source.
I think you'll find python lists are actually arrays not linked
lists...
I could also enumerate:

for i, j in enumerate(myarr ay):
print myarray[i], j # Prints each element twice

And this way I can keep referring to j instead of myarray[i], but I'm
still forced to use myarray[i-1] and myarray[i+1] to refer to the
previous and next elements. Being able to do j.prev, j.next seems more
intuitive.
Boundary conditions are a perenial problem in this sort of thing, what
to do at the start / end of the list...
Is there some other builtin somewhere that provides better functionality
that I'm missing?


I suppose you could use itertools...
from itertools import *
L=range(10)
(L1, L2, L3) = tee(L, 3)
L2.next() 0 L3.next() 0 L3.next() 1 for prev, current, next in izip(L1, L2, L3): print prev, current, next ....
0 1 2
1 2 3
2 3 4
3 4 5
4 5 6
5 6 7
6 7 8
7 8 9


--
Nick Craig-Wood <ni**@craig-wood.com> -- http://www.craig-wood.com/nick
Dec 18 '05 #2
On Sun, 18 Dec 2005 04:23:21 -0700, Joseph Garvin wrote:
When I first came to Python I did a lot of C style loops like this:

for i in range(len(myarr ay)):
print myarray[i]

Obviously the more pythonic way is:

for i in my array:
print i

The python way is much more succinct. But a lot of times I'll be looping
through something, and if a certain condition is met, need to access the
previous or the next element in the array before continuing iterating.
If you need to do that, then either you need to rethink your algorithm so
that you only need to access one element at a time, or you can to change
your loop so that you aren't accessing one element at a time.

For example, you might grab elements three at a time, and if the middle
one meets a certain condition process them, and if not, do nothing.

There is no shortage of ways to handle your situation. However, I can't
help but feel that you probably need to rethink what you are trying to do.
I can't speak for others, but I've never come upon a situation where I
needed to access the element before and the element after the current one.

[thinks...] Wait, no, there was once, when I was writing a parser that
iterated over lines. I needed line continuations, so if the line ended
with a backslash, I needed to access the next line (and potentially the
line after that, and so forth indefinitely). I dealt with that by keeping
a cache of lines seen, adding to the cache if the line ended with a
backslash.
I
don't see any elegant way to do this other than to switch back to the C
style loop and refer to myarray[i-1] and myarray[i+1], which seems
incredibly silly given that python lists under the hood are linked
lists, presumably having previous/next pointers although I haven't
looked at the interpeter source.
Python lists aren't linked lists? They are arrays.

I could also enumerate:

for i, j in enumerate(myarr ay):
print myarray[i], j # Prints each element twice
j is a built-in object used to make complex numbers. Or at least it
was, until you rebound it to the current element from myarray. That's bad
practice, but since using complex numbers is rather unusual, one you will
probably get away with.

And this way I can keep referring to j instead of myarray[i], but I'm
still forced to use myarray[i-1] and myarray[i+1] to refer to the
previous and next elements. Being able to do j.prev, j.next seems more
intuitive.


But that can't work, because j has no knowledge of the list it is part of:

myarray = ["spam", "parrot", "Spanish Inquisition"]
when i = 1, j = "parrot"

Since j is a string, it has no prev or next methods. How could "parrot"
possibly know that "spam" was the previous element?

You can't even have prev and next methods of the list myarray, because it
has no concept of the current element. The current element i is known by
the iterator used by the for loop, not the list it is iterating over.

You could possibly sub-class list, turning it into an iterator-like object
with next and prev methods, but be aware that "next" method has special
meaning to iterators.

You can probably create a generator or iterator that will do what you
want, but I suspect it won't be exactly straightforward .
--
Steven.

Dec 18 '05 #3
On Sun, 18 Dec 2005 23:36:29 +1100, Steven D'Aprano wrote:
Python lists aren't linked lists? They are arrays.


[slaps head for the stupid typo]
That should have been a full stop, not question mark. Python lists are not
linked lists, period.
--
Steven.

Dec 18 '05 #4
j> is a built-in object used to make complex numbers. Or at least it
was, until you rebound it to the current element from myarray. That's bad
practice, but since using complex numbers is rather unusual, one you will
probably get away with.


Is it?
j
Traceback (most recent call last):
File "<pyshell#0 >", line 1, in -toplevel-
j
NameError: name 'j' is not defined 1 + 2j (1+2j) j=4
1 + 2j (1+2j)


I am actually curious, as it doesn't appear to be, but you are usually
'right' when you say such things...

Max

Dec 18 '05 #5
Bas
Just make a custom generator function:
def prevcurnext(seq ): it = iter(seq)
prev = it.next()
cur = it.next()
for next in it:
yield (prev,cur,next)
prev,cur = cur, next

for (a,b,c) in prevcurnext(ran ge(10)):

print a,b,c
0 1 2
1 2 3
2 3 4
3 4 5
4 5 6
5 6 7
6 7 8
7 8 9

Cheers,
Bas

Dec 18 '05 #6
On Sun, 18 Dec 2005 04:50:20 -0800, Max Erickson wrote:
j is a built-in object used to make complex numbers. Or at least it
was, until you rebound it to the current element from myarray. That's bad
practice, but since using complex numbers is rather unusual, one you will
probably get away with.


Is it?


[snip example]

Well well, I'll be a monkey's uncle. You learn something new everyday.

Okay, I was wrong. There is no conflict between using j as a name and the
built-in j-as-syntax-for-complex-numbers, except for any potential
conflict in the programmers head.

That makes me feel a lot less guilty about all the times I wrote for j in
range loops :-)
--
Steven.

Dec 18 '05 #7
On Sun, 18 Dec 2005 04:23:21 -0700, Joseph Garvin <k0*****@kzoo.e du> wrote:
When I first came to Python I did a lot of C style loops like this:

for i in range(len(myarr ay)):
print myarray[i]

Obviously the more pythonic way is:

for i in my array:
print i

The python way is much more succinct. But a lot of times I'll be looping
through something, and if a certain condition is met, need to access the
previous or the next element in the array before continuing iterating. I
don't see any elegant way to do this other than to switch back to the C
style loop and refer to myarray[i-1] and myarray[i+1], which seems
incredibly silly given that python lists under the hood are linked
lists, presumably having previous/next pointers although I haven't
looked at the interpeter source.

I could also enumerate:

for i, j in enumerate(myarr ay):
print myarray[i], j # Prints each element twice

And this way I can keep referring to j instead of myarray[i], but I'm
still forced to use myarray[i-1] and myarray[i+1] to refer to the
previous and next elements. Being able to do j.prev, j.next seems more
intuitive.

Is there some other builtin somewhere that provides better functionality
that I'm missing?

I don't know of a builtin, but you could make an iterator that gives you
your sequence as (prev, curr, next) item tuples, where curr is the normal
single item in for curr in my_array: ... e.g.,
def pcniter(seq, NULL=NotImpleme nted): ... seqiter = iter(seq)
... prev = curr = NULL
... try: next = seqiter.next()
... except StopIteration: return
... for item in seqiter:
... prev, curr, next = curr, next, item
... yield prev, curr, next
... yield curr, next, NULL
... for prev, curr, next in pcniter('abcdef ', '\x00'): print '%8r'*3 %( prev, curr, next) ...
'\x00' 'a' 'b'
'a' 'b' 'c'
'b' 'c' 'd'
'c' 'd' 'e'
'd' 'e' 'f'
'e' 'f' '\x00' for prev, curr, next in pcniter(xrange( 4), 'NULL' ): print '%8r'*3 %( prev, curr, next)

...
'NULL' 0 1
0 1 2
1 2 3
2 3 'NULL'

If you want to assign back into myarray[i-1] etc, you'd still need to enumerate, but you could
combine with the above it was useful.

Regards,
Bengt Richter
Dec 18 '05 #8
Steven D'Aprano <st***@REMOVETH IScyber.com.au> wrote:
I can't speak for others, but I've never come upon a situation where I
needed to access the element before and the element after the current one.

[thinks...] Wait, no, there was once, when I was writing a parser that
iterated over lines. I needed line continuations, so if the line ended
with a backslash, I needed to access the next line (and potentially the
line after that, and so forth indefinitely). I dealt with that by keeping
a cache of lines seen, adding to the cache if the line ended with a
backslash.


In Python, that would be an excellent example use case for a generator
able to "bunch up" input items into output items, e.g.:

def bunch_up(seq):
cache = []
for item in seq:
if item.endswith(' \\\n'):
cache.append(it em[:-2])
else:
yield ''.join(cache) + item
cache = []

if cache:
raise ValueError("ext ra continuations at end of sequence")

[[or whatever you wish to do instead of raising if the input sequence
anomalously ends with a ``to be continued'' line]].
Alex
Dec 18 '05 #9
Steven D'Aprano wrote:
On Sun, 18 Dec 2005 23:36:29 +1100, Steven D'Aprano wrote:
Python lists aren't linked lists? They are arrays.


[slaps head for the stupid typo]
That should have been a full stop, not question mark. Python lists are not
linked lists, period.

All the more inexcusable then, because it's even easier to find the
next/previous element in an array! ;)
Thanks all, Bas/Bangt's solutions are very elegant =)

Dec 19 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
2815
by: Rob Meade | last post by:
Hi all, I went on an XML course over a year ago and have finally got around to having a use for it, but do you think I can actually remember anything - nope!.. Ok, here's what I want to do - I want to store an XML file with several elements that contain data for applications we've written - its going to be used by people in our team as...
3
1724
by: gordon.lear | last post by:
I am using MSXML 4.0 I am grabbing numerous RSS News Feeds and trying to parse the data and read it into a dB. The problem is that the RSS News feeds are not all the same when tunneled down in the item element. They ALL contain the nodes: title, description, link and pubDate. But they come in all different orders and have other child...
1
1890
by: saturnius | last post by:
Hi, I would like to have a navigation menu with prev/next in a top frame and in the main frame a PDF file. I think this might be possible with JavaScript: - get current file name - go to next prev in the list of 10 files Unfortunately I do not know JavaScript - that's why my post.... ;-) Could anybody point me in the right direction...
6
2729
by: Chris Styles | last post by:
Dear All, I've been using some code to verify form data quite happily, but i've recently changed the way my form is structured, and I can't get it to work now. Originally : The form is called "form1", and I have selects called "PORTA", "PORTB" ... etc...
6
1788
by: Lars Eighner | last post by:
I suppose this is a meta-html question, but it seems to go directly to an authoring issue. Which order of next, home (menu, index, main, contents), prev links do you prefer, and why? 1. next | home | prev or
6
2229
by: Patrick Coghlan | last post by:
I want to create about 4 forms with the same dimensions and background colours, similar to the forms one has to traverse when installing various software packages. I'm using Visual Studio and C++ (changing to C# soon) and can create separate forms, but I really just want to clone the first one, have the user select different options on each...
1
3303
by: jenson | last post by:
<?php /* * Created on Apr 13, 2007 * * To change the template for this generated file go to * Window - Preferences - PHPeclipse - PHP - Code Templates */ require_once 'init.php'; $con=mysql_connect("localhost","root",""); $dbc=mysql_select_db(test,$con)or die("Database select error:" . mysql_error($con));
8
10806
by: GaryDean | last post by:
I have a Wizard page and need to affect the next and previous buttons from my code-behind. I've googled around and found two solutions, and neither appear to work. I can access the SideBarList steps successfully with the following code... Control myContainer = (Control)Wizard1.FindControl("SideBarContainer"); DataList mySideBarList =...
16
3988
by: pupilstuff | last post by:
hi guys i just want to perform custom paging in which at the footer of the grid view ,there must be a pager 'pervious/next with numeric' this is what i did in aspx page <asp:GridView ID="TableGridView" OnPageIndexChanging="TableGridView_PageIndexChanging" runat="server" AutoGenerateColumns="False"
0
7548
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7472
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7986
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7504
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7832
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
1
5391
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3518
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3499
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1083
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.