4

I have an array: x = [ [1, 2], 1, 1, [2, 1, [1, 2]] ] in which I want to count every occurrence of the number 1, and store that number in the variable one_counter. x.count(1) returns only 2 occurrences of 1, which is insufficient.

My code below serves my purpose and stores 5 in one_counter, however it looks messy and feels unpythonic to me.

Any suggestions how I can improve its pythonicity and expand it into more-dimensional lists?

Thanks!

x = [[1, 2], 1, 1, [2, 1, [1, 2]]]

one_counter = 0

for i in x:
    if type(i) == list:
        for j in i:
            if type(j) == list:
                for k in j:
                    if k == 1:
                        one_counter += 1

            else:
                if j == 1:
                    one_counter += 1

    else:
        if i == 1:
            one_counter += 1
5
  • 1
    What does scale have to do with this? Commented Oct 9, 2011 at 7:26
  • @IgnacioVazquez-Abrams I guess he overused the word Scale,he might have meant expansion of his datatype into more dimensional lists. Commented Oct 9, 2011 at 7:38
  • @DhruvPathak Yes, sir! I misunderstood that for scale. Commented Oct 9, 2011 at 7:51
  • So how did you end up with this list, and why do you need this count? The whole thing seems oddly artificial. Commented Oct 9, 2011 at 8:50
  • @Karl Would you be upset if I said it was me practicing, hitting a road block, and asking for help? Commented Oct 11, 2011 at 3:53

3 Answers 3

8

You could use recursion:

def flatten_count(iterable, element):
    count = 0
    for item in iterable:
        if item == element:
            count += 1
        if isinstance(item, list):
            count += flatten_count(item, element)
    return count

Or more concisely:

def flatten_count(iterable, element):
    return sum(
        flatten_count(item, element) if isinstance(item, list) else item == element
        for item in iterable 
    )

Use like this:

>>> x = [[1, 2], 1, 1, [2, 1, [1, 2]]]
>>> print(flatten_count(x, 1))
5
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks so much, Mark! That makes perfect sense, and now I understand recursion better along with the handiness that is isinstance().
3

A hacky solution, working by conversion of datatype to string : http://codepad.org/vNEv6B8M

import re
x = [ [1, 2], 1, 1, [2, 1, [1, 2]] ]
nums = [int(i) for i in re.findall(r'\d+', str(x))]
print(nums.count(1))

Comments

2

I think it's better to separate this task into 2 parts.

Part 1

Part 1 is to create an generator which will flatten the input list.

def flatten_list(L):
    for i in L:
        if isinstance(i,list):
            for j in flatten_list(i):
                yield j
        else:
            yield i

Testing the output:

x = [[1, 2], 1, 1, [2, 1, [1, 2]]]

for i in flatten_list(x):
    print i

Output:

1
2
1
1
2
1
1
2

Part 2

Part 2 is to use the flattened list to count the number of occurrences of 1 in it:

print(sum(i==1 for i in flatten_list(x))) 

Output:

5

Note that i==1 returns True if i=1, and False if i is not equal to 1. But Trueis equal to 1 and False is equal to 0, so sum just calculates the number of True occurrences (which is equal to 5 in this case).

1 Comment

Thanks for breaking it down. I really appreciate it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.