Search code examples
pythonpython-3.xperformancelist-comprehension

List comprehension with complex conditions in python


I was looking up for ways to make my loop fast,then I found about list comprehensions.

I tried it on my own, but I don't fully understand it yet.

From what I learned researching about list comprehensions, the code I like to execute would be on the left side, followed by the conditions then the for loop.

So, it would basically look like this.

["Something I'd like to execute" Some conditions for loop]
Following this style, I did it like this.

The code I was trying to turn into a one liner:

graph = []

for g in range(M):
    satisfy = []
    graph_count = 0
    for i in range(N-1):
        count = 0
        for j in range(N):
            if i < j and count < 1:
                if graph_count < g:
                    count += 1
                    graph_count += 1
                    satisfy.append("1")
                else:
                    satisfy.append("0")
            elif i < j:
                satisfy.append("0")
    graph.append("".join(map(str,satisfy)))

My Attempt

graph = [[count+=1,graph_count+=1,satisfy.append("1") if graph_count < g else satisfy.append("0") and if i<j and count<1 else satisfy.append("0") if i<j for j in range(N) count=0 for i in range(N-1)] graph_count=0, "".join(map(str,satisfy)) for g in range(M)]

What am I doing wrong?


Solution

  • There are two kinds of optimization:

    • micro-optimization (statement level, e.g. f-strings are faster than format function)
    • macro optimization (algorithm, used data structures, etc)

    Optimizing algorithms may have much higher returns than spending the same effort on micro-optimizations.

    Here is my solution to your problem. After analyzing the expected output, I found some patterns and reduced the number of loops and allocations:

    from itertools import accumulate
    
    graph = []
    size = N * (N - 1) // 2
    s = list(reversed(list(accumulate(range(N)))))
    for g in range(M):
        satisfy = ["0"] * size
        for i in range(N - 1):
            if g > i:
                satisfy[size - s[i]] = "1"
    
        graph.append("".join(satisfy))