How can I generate a list and flatten it the same time in python?
<p>This is more of a refactoring question, as the code works as is. But since I am still learning <code>Python</code>, I thought there would be a better way to do this, and I spent a few hours now digging into the other possibilities, but can't get anywhere.</p>

<p>So I have the following statement:</p>

<p><code>numbers = [re.split(' ?- ?', ticket.text.strip()) for ticket in tickets]</code></p>

<p>which obviously generates a list of lists. However, I want to have just a single list of the numbers taken out from that regex.</p>

<p>So this is the second line of code that flattens the above list (I found this solution here, on <code>StackOverflow</code> btw):</p>

<p><code>flat = [item for setlist in numbers for item in setlist]</code></p>

<p>Main thing I am trying to achieve is to have this on 1 single line. Otherwise, I could of course have a normal <code>for .. in</code> loop, that would append each number to numbers list, but I like keeping it on 1 line. </p>

<p>If this is the best it can get, I would also love to know that please.. :)</p>

<p>Well, let's work through this one step at a time.
As a set of partially-nested for-loops, your code would be:</p>

<pre><code>numbers = []
for ticket in tickets:
    numbers.append(re.split(' ?- ?', ticket.text.strip())
flat = []
for setlist in numbers:
    for item in setlist:
        flat.append(item)
</code></pre>

<p>Talking through it:
You have a list of tickets. Each ticket becomes one setlist when you apply the regex split to it. You then want to grab all the items in the setlist and put them in a single list. You don't actually need to have a list of all the setlists (what you called <code>numbers</code>) at any point - that's just an intermediate stage.</p>

<p>Refactoring this to be completely nested:</p>

<pre><code>flat = []
for ticket in tickets:
    for item in re.split(' ?- ?', ticket.text.strip()):
         flat.append(item)
</code></pre>

<p>Now that we have a set of completely-nested for loops, it's trivial to refactor into a list or generator comprehension:</p>

<pre><code>flat = [item for ticket in tickets for item in re.split(' ?- ?', ticket.text.strip())]
</code></pre>

<p>It's a fairly long single line, but it is a single line.</p>

<p>Incidentally, a regex might not be the best way to parse out numbers like that - especially if you want the actual numbers rather than strings. <code>re.split()</code> is slower than <code>str.split()</code>, and this split is simple enough that it can be done by the latter. If the numbers are integers, try:</p>

<pre><code>flat = [int(item) for ticket in tickets for item in ticket.split('-'))]
</code></pre>

<p>And if they're floats, try:</p>

<pre><code>flat = [float(item) for ticket in tickets for item in ticket.split('-'))]
</code></pre>

<p>This works because the <code>int(str)</code> and <code>float(str)</code> builtins automatically ignore whitespace at the start and end of a given string, so you don't need a regex to conditionally match that whitespace. The resulting numbers can still be inserted into strings if you need to do that, and should also take up somewhat less space in memory. If the numbers are integers, you lose nothing. If they're floats, you lose very little - you lose the original precision of the number, and you might run into the limits on float size if you're working with really big or really tiny stuff (but that's unlikely - see <code>sys.float_info</code> for what those limits are).</p>

python