4

I have two lists, say

a = [10, 20, 30 , 40, 50 , 60] 
b = [30, 70, 110]

As you can see, list b consists of a list's a sum of elements with window = 2:

b[0] = a[0] + a[1] = 10 + 20 = 30 etc.

How can I get another list which will consist of fractions of list's a elements and b elemnts with a given window? In my example I want to get list:

c = [10/30, 20/30, 30/70, 40/70, 50/110, 60/110]
Sebastien D
  • 4,369
  • 4
  • 18
  • 46
John Keats
  • 79
  • 3

3 Answers3

4

You can use list-comprehensions for both tasks (creating b and c lists)

a = [10, 20, 30, 40, 50, 60]

b = [i+j for i, j in zip(a[::2], a[1::2])]
print(b)  # [30, 70, 110]

c = [x / b[i//2] for i, x in enumerate(a)]
print(c)  # [0.3333333333333333, 0.6666666666666666, 0.42857142857142855, 0.5714285714285714, 0.45454545454545453, 0.5454545454545454]

If you really want fractions, you can use the fractions module and its Fraction data type:

from fractions import Fraction

# same code as before

c = [Fraction(x, b[i//2]) for i, x in enumerate(a)]
print(c)  # [Fraction(1, 3), Fraction(2, 3), Fraction(3, 7), Fraction(4, 7), Fraction(5, 11), Fraction(6, 11)]

Note

As @LaurentH. notices in the comments, the above works only for chunks (you call them windows) of size 2. For a more general approach, you can define a generator that would yield them for you:

# taken from https://stackoverflow.com/a/312464/6162307
def yield_chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]    

b = [sum(chunk) for chunk in yield_chunks(a, 2)]
# same code

Example for n = 3:

n = 3
b = [sum(chunk) for chunk in yield_chunks(a, n)]
print(b)  # [60, 150]
c = [x / b[i//n] for i, x in enumerate(a)]
print(c)  # [0.16666666666666666, 0.3333333333333333, 0.5, 0.26666666666666666, 0.3333333333333333, 0.4]
Ma0
  • 15,057
  • 4
  • 35
  • 65
1
a = [10, 20, 30 , 40, 50 , 60] 
b = [30, 70, 110]

# take each value in a (multiply by 1.0 to get a double), and divide by the value in b in the corresponding index (i.e. indices 0,1 in a correspond with index 0 in b, and so on...)
c = [val*1.0/b[idx//2] for idx,val in enumerate(a)]

# here is the calculation using strings, to get the desired output by OP
d = ['{}/{}'.format(val, b[idx//2]) for idx,val in enumerate(a)]

print '{}\n{}'.format(c, d)

Output =

[0.3333333333333333, 0.6666666666666666, 0.42857142857142855, 0.5714285714285714, 0.45454545454545453, 0.5454545454545454]

['10/30', '20/30', '30/70', '40/70', '50/110', '60/110']
CIsForCookies
  • 12,097
  • 11
  • 59
  • 124
  • A couple of remarks: 1) if you are doing `val*1.0` to convert `val` to `float`, just do `float(var)`; it is more explicit. 2) Note that your code is Python 2.x 3) It does not seem to me that OP asked for a list of strings based on the way he formatted his question. – Ma0 Feb 26 '18 at 14:05
  • 1) my way is shorter. Don't see a reason for being explicit. 2) Known, OP didn't specify Py 2 or 3, 3) It was just a nice addition to look like what OP asked, not my actual answer – CIsForCookies Feb 26 '18 at 14:10
0

Here is my suggestion with one function for the sum and one function for the fraction, with the list and window width as parameters. It uses no external package and it is quite short, easy to read and understandable:

# Sum with a given window
def sumWithWindow(aList, window = 2):
    res = []
    mySum = 0
    for i,elem in enumerate(aList):
        mySum += elem
        if (i+1) % window == 0:
            res.append(mySum)
            mySum = 0
    return (res)


# Fraction with a given window
def fractionWithWindow(aList, window = 2):
    res = []
    b = sumWithWindow(aList, window)
    for i,elem in enumerate(aList):
        res.append(elem/b[int(i/window)])
    return (res)

# Example
a = [10, 20, 30 , 40, 50 , 60]
print(sumWithWindow(a, 2))
print(fractionWithWindow(a,2))

Here is also the one-liner style version, with list comprehension, a little bit less readable, but very short:

# Sum with a given window
def sumWithWindow(aList, window = 2):
    return [sum(aList[n:n+window]) for n in range(0,len(aList),window)]

# Fraction with a given window
def fractionWithWindow(aList, window = 2):
    return [elem/sumWithWindow(aList,window)[i//window] for i,elem in enumerate(aList)]

# Example
a = [10, 20, 30 , 40, 50 , 60]
print(sumWithWindow(a, 2))
print(fractionWithWindow(a,2))
Laurent H.
  • 6,316
  • 1
  • 18
  • 40