0

I am trying to write a python function that returns the indices of all even numbers in a list. However, it is only returning the index of the first even number.

My code

def indicesOfEvens(listOfInt):
"""return list with indices (indexes) of each even int
if no even ints in the list, return an empty list
if listOfInt isn't a list, or has something that isn't an int,
raise ValueError
"""
  if (type(listOfInt) != list):
    raise ValueError("must be list")
  for item in listOfInt:
    if (type(item) != int):
      raise ValueError("must be list of ints")
  index= []
  for i in range(0,len(listOfInt)):
    if listOfInt[i] % 2 == 0:
      return index + listOfInt[i]
  return index

Test Case

def test_indicesOfEvens_1():
  assert indicesOfEvens([11,20,35,44,57,63,42])==[1,3,6]
  • Good answer below already but, just an fyi, you don't need to close yourself off to just lists. [A lot of things are iterable in python](https://stackoverflow.com/questions/1952464/in-python-how-do-i-d) –  Jun 08 '18 at 23:41
  • As Terminus suggests, usually in Python you just want to "duck type" things—a function that works on any iterable of any integral values is more useful than one that only works on lists of ints. But on the rare occasions when you really do want a list of ints you still usually want to allow subclasses of list or subclasses of int, right? So you usually want `if not isinstance(listOfInt, list):` rather than `if type(listOfInt) != list:`. Exact `type(…)` checks are mostly only useful for micro-optimizations ("I know this is exactly type X, so I can make some assumptions for speed…"). – abarnert Jun 09 '18 at 00:41
  • Meanwhile, as a side note: you don't have to do `for i in range(0, len(listOfInt)):` and then keep using `listOfInt[i]`, you can just do `for val in listOfInt:` and use `val`. This makes your code shorter, easier to read, and harder to get wrong. – abarnert Jun 09 '18 at 00:44

2 Answers2

2

I would like to share with you that you don't have to do a return in this part of code, but you do have to use += or append. So instead of:

     return index + listOfInt[i]

… just do:

    index.append(listOfInt[i])

So the solution is:

def indicesOfEvens(listOfInt):
    """return list with indices (indexes) of each even int
    if no even ints in the list, return an empty list
    if listOfInt isn't a list, or has something that isn't an int,
    raise ValueError
    """
    if (type(listOfInt) != list):
        raise ValueError("must be list")
    for item in listOfInt:
        if (type(item) != int):
            raise ValueError("must be list of ints")
    index= []
    for i in range(0,len(listOfInt)):
        if listOfInt[i] % 2 == 0:
            index.append(listOfInt[i])
    return index

def test_indicesOfEvens_1(): 
     assert indicesOfEvens([11,20,35,44,57,63,42])==[1,3,6]
abarnert
  • 354,177
  • 51
  • 601
  • 671
1

How about just using a list comprehension instead of your for loop. Basically, you test if the value is even by using the modulo operator:

def indices_of_evens(list_of_ints):
  if (type(list_of_ints) != list):
    raise ValueError("Error: Must be a list")
  for item in list_of_ints:
    if (type(item) != int):
      raise ValueError("Error: Must be a list of ints")
  return [ind for ind, x in enumerate(list_of_ints) if x % 2 == 0]

The issue with your current code is that you need to append the index value to your indices list (in your code this was the list index) rather than returning to early:

indices = []
for i in range(0, len(list_of_ints)):
  if list_of_ints[i] % 2 == 0:
    indices.append(i) # <--- This line was changed from the equivalent of return indices + list_of_ints[i]
return indices 

Note: I changed your variable names from camelCase to snake_case as the latter is what is usally used in python

Sash Sinha
  • 18,743
  • 3
  • 23
  • 40