misheekoh
misheekoh

Reputation: 460

Storing a list of results in a list

My code takes a list of numbers and find it's divisors. Now, let's say I have a list [12,15,20]. Now, as I go through each element in the list, my aim is to store all the divisors of 12,15 and 20 in separate lists so I could reference back to them later

E.g.,

divisors of 4 are 1, 2, 4

divisors of 12 are 1, 2, 3, 4, 6, 12

So, the result should look like [[1,2,4],[1,2,3,4,6,12]]

Now, after finishing finding divisors of 4, append them to a list. Then store that list in the 1st index of new list called M. Then, go on to find divisors of 12, append them to a list and store that list at the 2nd index of list M

However, I am not able to do this and this is my attempt and a visualizer to help with understanding what's going on in the code http://goo.gl/InJxV3 :

def fn(N):
    result = []
    G = []
    if type(N) is list:                          #checks input for list type
        for i in N:                          #for elements in input. e.g., 12,15,20
            for j in range(1,i+1):           #j is the numbers that we're going to divide i with
                if(i%j == 0 and i >= j):     #checks if remainder is 0, if it is, then j is a divisor/multiple of i
                    result.append(j)         #appends j to list result
            G.append([result])               # <----- NOT RIGHT.Attempting to create a new list to store result.
return print(G[:])

fn([4,12,15])

Will be glad to get some guidance, help, advice. Also, I would prefer not to use the zip() function.

Upvotes: 0

Views: 1000

Answers (4)

pzp
pzp

Reputation: 6597

Instead of writing a function to find the factors of all of the numbers in a list of integers, first write a function to find the factors of one number:

def factor(n):
    factors = set()

    for x in range(1, int(n**0.5) + 1):
        if n % x == 0:
            factors.add(x)
            factors.add(n//x)

    return sorted(factors)

Now that you can find the factors of a single number, you can use map() to apply it to a list of numbers:

map(factor, [4, 12, 15])

Alternatively, you can use a list comprehension:

[factor(n) for n in [4, 12, 15]]

Both of these methods return the following:

[[1, 2, 4], [1, 2, 3, 4, 6, 12], [1, 3, 5, 15]]

If you would like to, you can make either one of them into a function:

def factor_list(arr):
    return map(factor, arr)

factor_list([4, 12, 15])

As you can see, breaking the initial problem down from finding the factor of a list of numbers to finding the factor of one number makes the overall problem much easier and the solution much simpler.

EDIT 1

The following is an explanation of why I used n//x as opposed to just n/x, as per the OP's request.

// is the floor division operator in Python. It is essentially equivalent to dividing the two numbers and then calling math.floor() on the quotient. The reason we need to do this is because n/x would use "true division," which as you said, returns a float. Since we are looking for integral factors, it only makes sense to force the numbers to be ints.

If you really wanted to, you could replace my factor function with the algorithm you used in your question without changing the behavior of the program:

def factor(i):
    result = []
    for j in range(1, i+1):
        if i % j == 0:
            result.append(j)
    return result

Or, the shorter equivalent:

def factor(i):
    return [j for j in range(1, i+1) if i % j == 0]

However, the algorithm I used is more efficient, as it only needs to check up until the square root of the number being factored.

EDIT 2

I see from some other answers that you are possibly looking for the shortest solution:

fn=lambda a:map(lambda i:[j for j in range(1, i+1)if i%j==0],a)

I believe I win with the above, 63 character one-liner :). Although this solution is very short, I believe my first solution is better, as it is much more readable. Remember, shorter isn't always better!

Upvotes: 2

midori
midori

Reputation: 4837

If that's what you want:

def fn(N):
    result = []
    if isinstance(N, list):
        for i in N:
            G = []
            for j in range(1,i+1):
                if not i%j and i >= j:
                    G.append(j)
            result.append(G)
    return result

Or if you want short version:

def fn(n):
    return [[j for j in range(1,i+1) if not i % j and i >= j] 
            for i in n if isinstance(n, list)]  

print fn([4, 12, 15])

Output:

[[1, 2, 4], [1, 2, 3, 4, 6, 12], [1, 3, 5, 15]]

Upvotes: 1

sunkuet02
sunkuet02

Reputation: 2442

You can try this:

def fn(N):
    result = []
    G = []
    if type(N) is list:                          #checks input for list type
        for i in N:                          #for elements in input. e.g., 12,15,20
            for j in range(1,i+1):           #j is the numbers that we're going to divide i with
                if(i%j == 0 and i >= j):     #checks if remainder is 0, if it is, then j is a divisor/multiple of i
                    result.append(j)         #appends j to list result
            G.append(result)
            result = []
    print(G)
    return G

fn([4,12,15])

Upvotes: 1

Karoly Horvath
Karoly Horvath

Reputation: 96258

  • You never create a new list. This should be inside the loop: result = []
  • return print(G[:]) You either print, or return. Mixing them doesn't make sense, as print returns nothing (None).

Upvotes: 1

Related Questions