3

I am using Python to write a program that looks through lists of lists and changes values.

In my list of lists I have 3's and I want to find their index. Right now I can only get it to work on the first row. I want it to find 3's on any of the lists in "numbers."

Here is some sample code to wash away the mud:

numbers = [
    [3, 3, 3, 5, 3, 3, 3, 3, 6],
    [8, 0, 0, 0, 4, 7, 5, 0, 3],
    [0, 5, 0, 0, 0, 3, 0, 0, 0],
    [0, 7, 0, 8, 0, 0, 0, 0, 9],
    [0, 0, 0, 0, 1, 0, 0, 0, 0],
    [9, 0, 0, 0, 0, 4, 0, 2, 0],
    [0, 0, 0, 9, 0, 0, 0, 1, 0],
    [7, 0, 8, 3, 2, 0, 0, 0, 5],
    [3, 0, 0, 0, 0, 8, 0, 0, 0],
    ]
a = -1
while a:
    try:
        for row in numbers:
            a = row[a+1:].index(3) + a + 1
            print("Found 3 at index", a)
    except ValueError:
        break

When I run it I get:

Found 3 at index 0
Found 3 at index 1
Found 3 at index 2
Found 3 at index 4
Found 3 at index 5
Found 3 at index 6
Found 3 at index 8

Which shows that it is working but only on the first row.

Thanks!

cbbcbail
  • 1,651
  • 4
  • 16
  • 27
  • Do you want to find `3` or `0` ? what's the purpose of that slicing on `row` ? – moooeeeep Dec 29 '11 at 22:06
  • I'm not sure what you mean by "working". Your code is definitely examining more than just the first row, but probably not in the way that you would like. Work through your code by hand (with pencil and paper if necessary) to see what Python is doing. Be sure to keep careful track of the value of `a`. – John Y Dec 29 '11 at 22:12
  • What I mean by "working" is that it only "does what is supposed to do" on the first row. It most certainly is not looking at the entire list of lists. – cbbcbail Dec 29 '11 at 22:14
  • please make more clear what your code is supposed to do. and verify that it actually works as intended even on the first row. – moooeeeep Dec 29 '11 at 22:16
  • @cbbcbail: The only reason it doesn't look at the entire list of lists is that **you** have told it to stop prematurely. It **does** look at more than first row. Please, please go through your code (pretend *you* are the Python interpreter) and keep track of what `a` is. Notice that the value of `a` will affect `row[a+1:]`. – John Y Dec 29 '11 at 23:34
  • @cbbcbail: Also, do not merely edit your results by changing instances of `0` to `3`. That is not what the program is doing. Please **run** the program again, and see what the results *really are*. – John Y Dec 29 '11 at 23:37
  • @JohnY Yes I figured out my problems. I do indeed realize that my results were incorrect. I also realize that changing the 0's to threes would fix the program because I had copied the wrong thing from IDLE. And the results were meant to be 3's – cbbcbail Dec 29 '11 at 23:50
  • @cbbcbail: Fine, you meant `3` instead of `0`. But look at the output you have listed above. You are showing seven lines, with `3` being found at indices 0, 1, 2, 4, 5, 6, 8. Those are the indices that your original program gave you. Your current program will not print seven lines anymore. Try it and see what I mean. Copy the code *from this question* and run it. See what you get. – John Y Dec 29 '11 at 23:56

5 Answers5

2

If you only want to get the row index, iterate over numbers using enumerate [docs] and test whether 3 is in the list using in [docs]:

for index, row in enumerate(numbers):
    if 3 in row:
        print "3 found in row %i" % index

For row and column index, iterate over both lists:

for index, row in enumerate(numbers):
    for col, value in enumerate(row):
        if value == 3:
            print "3 found in row %i at position %i" % (index, col)

If you just want to get the indexes in a new list, you can use list comprehension [docs]:

indexes = [(row, col) for row, r in enumerate(numbers) for col, val in enumerate(r) if val == 3]
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
2

Here's a little code snippet to get you started:

>>> for i, row in enumerate(numbers):
        if 3 in row:
            print i, row.index(3)   

1 8
2 5
7 3
8 0

>>> numbers[1][8]
3
>>> numbers[2][5]
3
>>> numbers[7][3]
3
>>> numbers[8][0]
3
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
1

Try the following:

[[i for i, v in enumerate(row) if v == 3] for row in numbers]

This will result in a list of lists where each entry in the inner lists is an index of a 3 in the corresponding row from the original list:

[[], [8], [5], [], [], [], [], [3], [0]]

You said you were looking for 3 but your code appears to be looking for 0, which do you want?

You could use it like this:

threes = [[i for i, v in enumerate(row) if v == 3] for row in numbers]
for row, indices in enumerate(threes):
    for col in indices:
        print "3 found in row %d, column %d" % (row, col)
Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • Not exactly what I am looking for. I want a way to run the code that I have running for "row" except I want it to run for all rows. – cbbcbail Dec 29 '11 at 22:09
  • @cbbcbail - See my edit which shows how you might use the result. – Andrew Clark Dec 29 '11 at 22:13
  • I +1'd for the nested comprehension. cbbcbail, it is worth the effort to dissect @F.J 's initial answer. – yurisich Dec 30 '11 at 00:00
  • I liked [your answer about Python sets](http://stackoverflow.com/a/8675170/377270) -- it had a link to documentation. :) – sarnold Dec 30 '11 at 01:06
  • @sarnold - I removed it because I realized the page I was linking to was for the deprecated sets module, not the built-in set type. The correct documentation didn't reference `__eq__()` which was the only difference between my answer and the other, so it was kind of pointless. Links to docs always make answers better though, I agree :) – Andrew Clark Dec 30 '11 at 01:09
  • Ah, I guess I can understand it then... Thanks! :) – sarnold Dec 30 '11 at 01:11
1

Instead of displaying the information, let's actually build up a data structure that gives us the "coordinates" of every 3:

x = [
    (r, c)
    for r, row in enumerate(numbers)
    for c, cell in enumerate(row)
    if cell == 3
]

And we can easily verify it:

assert(all(numbers[r][c] == 3 for r, c in x))

But if you want to replace values, it's silly to try to build up this list and then use it to manually go back in and replace stuff. Much cleaner to just produce the desired output directly. That is, "a list of lists such that the value is None (let's say, for the sake of argument) if the corresponding original value is 3, and otherwise the original value)".

That's spelled like

[[None if cell == 3 else cell for cell in row] for row in numbers]
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
0

Try using scipy/numpy to do this

import scipy as sp
matrix = your_matrix #write your matrix here. I left it.
x,y = sp.where(matrix == 3)
for i in range(len(x)):
    print x[i],y[i]
Vishwanath
  • 835
  • 1
  • 7
  • 19