Quick checkup on python list comprehension - python

I currently generate lists using following expression (T and no_jobs are integers):
for i in xrange(no_jobs):
row = row + T * [i]
The first thing I came up with for converting it into a list comprehension statement was:
[T*[i] for i in xrange(no_jobs)]
But this obviously creates a nested list which is not what I'm looking for. All my other ideas seems a litle clunky so if anyone has a pythonic and elegant way of creating these types of lists I would be gratefull.

Nested loops.
[i for i in xrange(no_jobs) for x in xrange(T)]

But this obviously creates a nested list which is not what I'm looking for.
So just flatten the result. List addition is concatenation, so we can put all the lists together by 'summing' them (with an empty list as an "accumulator").
sum((T*[i] for i in xrange(no_jobs)), [])

Related

Is there a way to create a list comprehension from this?

I just learned how to create list comprehensions and I was looking back through my past projects to see where I can create comprehensions. I was successful with several, but then I got to this part of the code and I was wondering if there was any way to create a list comprehension from this:
scores = util.Counter()
for l in self.legalLabels:
scores[l] = self.weights[l] * trainingData[i]
Maybe I'm just thinking a bit too hard for this but I was wondering if there was any way to create a comprehension using this?
I was thinking something like:
[(scores(l) = self.weights[l] * trainingData[I]) for l in self.legalLabels]
but this does not work in terms of attributing each value to scores[l].
Any help would be greatly appreciated!
If util.Counter() is a dictionary like collections.Counter, you can update it with a dictionary via its update method. So you can use:
scores = util.Counter()
scores.update({L: self.weights[L] * trainingData[i] for L in self.legalLabels})
Then for some label x, you can access the result via scores[x].
List comprehension are for lists, dictionary comprehensions for dictionaries. The latter are mentioned in the docs.
EDIT: I didn't pay attention to scores = utils.Counter(), so I provided an answer which is list comprehension. See #jpp's answer for correct approach.
Your approach is right, but there is no assignment within comprehension. You must make one outside of it
scores = [self.weights[l] * trainingData[I]) for l in self.legalLabels]

How to have best use of Python lists?

My question is te following:
I'm new to Python programming and I'm a little confused about the correct use of lists.
When I want for example to create a list of 10 elements I am doing something like:
list = [None for x in range(10)]
And when I have something to put on it, I do:
list[lastPosition] = data
But after some research I noticed that this use for lists is not efficient or recommended. But how other way could a list be inicialized before I have all the data? My idea is to have a list (specially something like Java's Collections) inicialized and as the data comes I fill it.
I hope my question is clear enough.
If you don't know in advance how many elements will be in the list,
then don't try to allocate 10 elements. Start with an empty list and use the append function to append to it:
lst = []
...
lst.append(value)
If for some reason you really need to initialize a list to a constant size,
and the initial elements are immutable values,
then you can do that like this:
lst = [None] * 10
If the initial elements are mutable values,
you most probably don't want to use this technique,
because all the elements will all point to the same instance.
In that case your original technique is mostly fine as it was:
lst = [SomeClass() for _ in range(10)]
Note that I renamed the variable from list to lst,
because list is a built-in class in Python,
and it's better to avoid such overlaps.

List comprehension with list and list of tuples

In my Python 2.7.5 code I have the following data structures:
A simple list...
>>> data["parts"]
['com', 'google', 'www']
...and a list of tuples...
>>> data["glue"]
[(1L, 'com'), (3L, 'google')]
When entering the code where these structures exist I will always know what is in data["parts"]; data["glue"], at best, will contain "matching" tuples with what is in data["parts"] - worst case data["glue"] can be empty. What I need is to know is the parts that are missing from glue. So with the example data above, I need to know that 'www' is missing, meaning it is not in any of the tuples that may exist in data["glue"].
I first tried to produce a list of the missing pieces by way of various for loops coupled with if statements but it was very messy at best. I have tried list comprehensions and failed. Maybe list comprehension is not the way to handle this either.
Your help is much appreciated, thanks.
You can use set difference operations.
print set(data['parts'])-set(i[1] for i in data['glue'])
>>> set(['www'])
or with simply using list comprehensions:
print [i for i in data['parts'] if i not in (j[1] for j in data['glue'])]
>>> ['www']
The set operation wins in the speed department, running the operation 10,000,000 times, we can see that the list comprehension takes over 16s longer:
import timeit
print timeit.timeit(lambda : set(data['parts'])-set(i[1] for i in data['glue']), number=10000000)
>>> 16.8089739356
print timeit.timeit(lambda : [i for i in data['parts'] if i not in (j[1] for j in data['glue'])], number=10000000)
>>> 33.5426096522
You can use list comprehensions here. Maybe the simplest thing would be to create a set of all indices, then return the missing indices. Note this answer will give you all the missing components, even if there are duplicates in the parts array (for example, if "www" appeared twice in parts). This would not be the case with set comprehension.
# set of 0-based indices extracted from the 1-based tuples
indices = set(glue_tuple[0] - 1 for glue_tuple in data['glue'])
# array of missing parts, in order
missing_parts = [part for i, part in enumerate(data["parts"]) if i not in indices]

Initialising an n-length tuple of lists

Is there a more efficient, simpler way to create a tuple of lists of length 'n'?
So in Python, if I wanted to create a list of lists I could do something like:
[[] for _ in range(list_length)]
And to create a tuple of lists of a similar nature I could technically write:
tuple([[] for _ in range(list_length)])
But is this computationally inefficient, could it be written in a nicer way?
Warning: For anyone else who thought it was good idea to put mutable objects such as lists inside a tuple (immutable); it actually appears to be generally faster (computationally) to just use a list (in my case a list of lists).
Use a genex instead of a LC.
tuple([] for _ in range(list_length))
Try this:
tuple = (elements,) * list_length

Sorting a sublist within a Python list of integers

I have an unsorted list of integers in a Python list. I want to sort the elements in a subset of the full list, not the full list itself. I also want to sort the list in-place so as to not create new lists (I'm doing this very frequently). I initially tried
p[i:j].sort()
but this didn't change the contents of p presumably because a new list was formed, sorted, and then thrown away without affecting the contents of the original list. I can, of course, create my own sort function and use loops to select the appropriate elements but this doesn't feel pythonic. Is there a better way to sort sublists in place?
You can write p[i:j] = sorted(p[i:j])
This is because p[i:j] returns a new list. I can think of this immediate solution:
l = p[i:j]
l.sort()
a = 0
for x in range(i, j):
p[x] = l[a]
a += 1
"in place" doesn't mean much. You want this.
p[i:j] = list( sorted( p[i:j] ) )

Categories