19

I was trying to understand Kadane's algorithm from Wikipedia, when I found this:

def max_subarray(A):
    max_ending_here = max_so_far = A[0]
    for x in A[1:]:
        max_ending_here = max(x, max_ending_here + x)
        max_so_far = max(max_so_far, max_ending_here)
    return max_so_far

I'm not familiar with Python. I tried to google what this syntax does but I couldn't find the right answer because I didn't know what's it called. But, I figured A[1:] is the equivalent of omitting A[0], so I thought for x in A[1:]: is equivalent to for(int i = 1; i < A.length; i++) in Java

But, after changing for x in A[1:]: to for x in range(1,len(A)), I got the wrong result

Sorry if this is a stupid question, but I don't know where else to find the answer. Can somebody tell me what this syntax does and what is it called? Also, could you give me the equivalent of for x in A[1:]: in Java?

Margo Eastham
  • 605
  • 1
  • 10
  • 20

6 Answers6

39

Here are some of the example that I have tried

>>> a=[1,5,9,11,2,66]

>>> a[1:]
[5, 9, 11, 2, 66]

>>> a[:1]
[1]

>>> a[-1:]
[66]

>>> a[:-1]
[1, 5, 9, 11, 2]

>>> a[3]
11

>>> a[3:]
[11, 2, 66]

>>> a[:3]
[1, 5, 9]

>>> a[-3:]
[11, 2, 66]

>>> a[:-3]
[1, 5, 9]

>>> a[::1]
[1, 5, 9, 11, 2, 66]

>>> a[::-1]
[66, 2, 11, 9, 5, 1]

>>> a[1::]
[5, 9, 11, 2, 66]

>>> a[::-1]
[66, 2, 11, 9, 5, 1]

>>> a[::-2]
[66, 11, 5]

>>> a[2::]
[9, 11, 2, 66]

I think you can understand more by this examples.

Saurabh Lende
  • 953
  • 2
  • 13
  • 19
14

This is array slice syntax. See this SO question: Explain Python's slice notation .

For a list my_list of objects e.g. [1, 2, "foo", "bar"], my_list[1:] is equivalent to a shallow copied list of all elements starting from the 0-indexed 1: [2, "foo", "bar"]. So your for statement iterates over these objects:

for-iteration 0: x == 2 
for-iteration 1: x == "foo" 
for-iteration 2: x == "bar" 

range(..) returns a list/generator of indices (integers), so your for statement would iterate over integers [1, 2, ..., len(my_list)]

for-iteration 0: x == 1 
for-iteration 1: x == 2
for-iteration 2: x == 3

So in this latter version you could use x as an index into the list: iter_obj = my_list[x].

Alternatively, a slightly more pythonic version if you still need the iteration index (e.g. for the "count" of the current object), you could use enumerate:

for (i, x) in enumerate(my_list[1:]):
    # i is the 0-based index into the truncated list [0, 1, 2]
    # x is the current object from the truncated list [2, "foo", "bar"]

This version is a bit more future proof if you decide to change the type of my_list to something else, in that it does not rely on implementation detail of 0-based indexing, and is therefore more likely to work with other iterable types that support slice syntax.

Community
  • 1
  • 1
Preet Kukreti
  • 8,417
  • 28
  • 36
  • Oh I see. When I changed it `for x in A[1:]` to `for x in range(1, len(A))` I should've accessed the element using `A[x]` instead of just `x`. Is that any difference between `for x in A[1:]: doSomething(x)` and `for x in range(1, len(A)): doSomething(A[x])` ? – Margo Eastham Dec 26 '14 at 04:13
  • @MargoEastham, yes you could do `A[x]`, instead. You may want to do this if you want to use the index for something else. The former syntax is considered more "pythonic", and the latter more verbose. The former method (iterating over the objects) may be more future proof to work with objects other than lists that support slice syntax. The latter version assumes indexing into the collection by 0-based integers. Practically though, it should not make any difference. It is more about type-dependency/assumptions and code clarity. – Preet Kukreti Dec 26 '14 at 04:17
  • Thanks. Now I know what's it all about – Margo Eastham Dec 26 '14 at 04:28
  • @MargoEastham: Also note that you can supply an optional second arg to enumerate to specify a starting index. Thus `for i, x in enumerate(my_list[1:], 1):` will start i at 1. – PM 2Ring Dec 26 '14 at 05:29
2

Unlike other languages, iterating over a sequence in Python yields the elements within the sequence itself. This means that iterating over [1, 2, 4] yields 1, 2, and 4 in turn, and not 0, 1, and 2.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 1
    Right, so in Java there's also `for(int x : A)` where A is an `int[]` integer array. Could you explain more about the difference between `for x in A` and `for x in A[1:]` ? If `A[1:]` means element 1 to last element (without zeroth element). Then, is `for x in A[1:]` just iterating from element 1 to last element(ignoring the element `A[0]` ? – Margo Eastham Dec 26 '14 at 04:07
  • @MargoEastham Yes, that's exactly it. – Waleed Khan Dec 26 '14 at 04:09
  • @MargoEastham: That's the overall effect, but the specific effect is that a new sequence is generated that is missing the first element, and then *that* sequence is iterated over. – Ignacio Vazquez-Abrams Dec 26 '14 at 04:11
  • @IgnacioVazquez-Abrams got it! I changed the code to `for x in range(1, len(A)):` and then accessed the element `A[x]` instead of `x` and it worked. I'm just curious, what's the specific benefit of generating a new sequence? Isn't `for x in A[1:]:` the same with `A = A[1:]` and then `for x in A:` ? – Margo Eastham Dec 26 '14 at 04:21
  • 1
    You don't slice the sequence because it gives you any specific benefit, you slice it because the algorithm requires you to operate on all elements but the first. – Ignacio Vazquez-Abrams Dec 26 '14 at 04:27
  • I don't really think the "Unlike other languages" is appropriate given that many other languages contain a similar construct, [even the venerable C++ has one now](http://en.cppreference.com/w/cpp/language/range-for). What does make sense would be to say that Python does *not* have the traditional "generalized for-loop" from the C-family of languages that allows you to do just about anything you want. – Rufflewind Dec 26 '14 at 04:28
  • @Rufflewind: Most of those languages only have them because the designers have seen how successful such a construct has been in Python and similar languages. – Ignacio Vazquez-Abrams Dec 26 '14 at 04:30
  • @IgnacioVazquez-Abrams: whether that's true or not is not relevant to this issue. – Rufflewind Dec 26 '14 at 04:33
2

What does "for x in A[1:] mean?

There are two parts to this. First, let's consider A[1:], which is slice notation on a list or array. Consider the following list:

A = [3,4,5,6]

In this example A[0] is 3 and A[1] is 4 and so on. When you use the : that can mean take everything or everything from a certain index. So A[1:] is the slice notation that says, "Take elements 1 to the end" of the list. So in my simple example A[1:] gives you a slice of the list that is [4,5,6]

The second have of the question is about the for x... part. In this case this is the Python notation that says for each element in the list. So:

A = [3,4,5,6]
for x in A[1:]:  #remember A[1:] is [4,5,6]
    print(x)

This will print 4 on the first loop, 5 on the second loop, and 6 on the third loop.

user1563247
  • 516
  • 1
  • 7
  • 20
1
A = [1, 2, 3]

A[1:] == [2, 3]

This is used to truncate your list from the first element.

And note that lists are mutable, if you find something like A[:] that means, they want to create a double of this list, without altering the original list, and use A[::-1] instead of reversed(A) to reverse the list.

Dan D.
  • 73,243
  • 15
  • 104
  • 123
Abdelouahab
  • 7,331
  • 11
  • 52
  • 82
0

Simply A[1:] means access elements from 1st position (don't consider A[0]). That's the only logic we need to consider.

A=[23,45,6,77,456,3]
print(A[1:])

output:

45,6,77,456,3
Pasindu Perera
  • 489
  • 3
  • 8