Python multiple list comprehensions containing ranges of tuples in one list - python

I need a list like this:
[(16,2), (14,3), (15,3), (16,3), (18,3), (19,3), (12,4), (13,4), (14,4)]
But much, much longer. There are certain really large range patterns in this list, but also irregularities. So it would be unfeasible to write down all tuples, but I can't make a simple listcomp either.
I wanted to use:
[(16,2), (x,3) for x in range(14,19), (x,4) for x in range(12,14)]
But according to the docs, [x, y for ...] is not allowed, and my example is interpreted as an unparenthesed tuple of 2 parenthesed tuples, instead of a tuple followed by a list comprehension.
Any solutions?

Try this:
[(16, 2)] + [(x,3) for x in range(14,19)] + [(x,4) for x in range(12,14)]

From your question is not clear if you're trying to increase the second index at every new range.
If that's the case you could put all the ranges in a list and use itertools.count():
from itertools import count
indexes = [(16,17), (14, 20), (12, 15)]
[(x, n) for i,n in zip(indexes,count(2)) for x in range(*i)]
Which give exactly:
[(16, 2), (14, 3), (15, 3), (16, 3), (17, 3), (18, 3), (19, 3), (12, 4), (13, 4), (14, 4)]

You could create separate lists and then append them to each other.
a = [(16, 2)]
b = [(x, 3) for x in range(14, 19)]
c = [(x, 4) for x in range(12, 15)]
a.extend(b)
a.extend(c)

Related

Sorting list of tuples (Python)

I am new in python and for practice reasons, I am trying to solve the following task:
Given a list of tuples
A = [(17, 8), (17, 12), (7, 2), (9, 15), (9, 17), (1, 4), (3, 9), (12, 14)]
My goal is: to sort in (n log n) time in descending order the list according to the first element of the set and if the first element of two sets are the same, sorting in descending order according to the second element. --> x <= x', y <= y'
So, I want to get the result:
A = [(17, 12), (17, 8), (12, 14), (9, 17), (9, 15), (7, 2), (3, 9), (1, 4)]
I have tried using the following code:
A.sort(reverse = True, key=lambda x: x[0] )
But it just sorts according to the first element and I do know if it is in n log n time.
Could you please help me with that?
Thank you!
To sort based on both values, remove the key function:
>>> A.sort(reverse = True)
>>> A
[(17, 12), (17, 8), (12, 14), (9, 17), (9, 15), (7, 2), (3, 9), (1, 4)]
And yes, Python sorts in O(n log n), for more, check out Timsort on Wikipedia, the algorithm Python uses for sorting.
Python's inbuilt sorted() method with a comparator function(Similar to C++) will work
sorted(tup, key = lambda x: x[0])
Tuples are naturally sorted by the first element, then the second:
A.sort(reverse = True)
Output as requested.
There you go:
A = [(17, 8), (17, 12), (7, 2), (9, 15), (9, 17), (1, 4), (3, 9), (12, 14)]
reverse_sorted = []
for item in reversed(sorted(A)):
reverse_sorted.append(item)
print(reverse_sorted)
As to add to the other's excellent answers. Search on Google with "python list sort time complexity" will return for you what you seek regarding python's sort time complexities (that others have already written above).
In addition, if you need to move away from using python's inbuilt sort function. There are many different sorting algorithms created over the years that you can recreate that have the desired time complexities. It would be a good "training" exercise if you're new to programming in general.

Storing python list of tuples in a redis sorted set where second element of tuple is used as score

I have a Python list of tuples like so:
lst = [(22, -150.0), (23, -150.0), (18, -148.5), (15, -99.4), (5, -75.75), (4, -49.2), (13, -49.0), (9, -41.3), (20, -25.5), (17, -22.3), (10, -13.1), (16, -12.5), (14, -9.8), (3, -8.5), (1, -8.4), (12, -1.5), (7, -0.6), (2, -0.4), (6, 1.7), (21, 2.7)]
How do I pass that into a redis sorted set, such that the second value in each tuple is used as the score? I tried zadd(sorted_set, *lst), but I'm getting the error value is not a valid float.
The zadd method of redis.StrictRedis expects arguments in the form of
zadd(key, score1, name1, score2, name2, ...)
In other words, you need to reverse and unpack the inner tuples as well:
In [6]: r = redis.StrictRedis(...)
In [8]: r.zadd('sset', *(y for x in lst for y in x[::-1]))
Out[8]: 20
Redis.zadd and StrictRedis.zadd behave differently -- see README for more details. So if you use redis.Redis instead of redis.StrictRedis (you shouldn't), do not reverse tuples:
r.zadd('sset', *(y for x in lst for y in x))

Python: Is this list index's value equal to any other index's value?

I have a list of tuples that starts out empty and is appended with new user-generated tuples.
if left_mouse == True:
generic_list.append((mouse_position_x, mouse_position_y))
To prevent having multiple tuples with the same (x, y) data, I want to iterate through the list and check if the newest tuple is the same as any other tuple in the list, and if it is, replace the old tuple with the new one.
for tuple in tuple_list:
if tuple_list[-1].position == tuple_list[i].position:
tuple_list.remove(i)
I know what I've got is wrong, but I don't know why or how to move forward. Any help would be really appreciated.
Edit: I'm now using set() and it works perfectly. Thanks everyone.
i recommend using a set (instead of a list):
>>> d = {tuple(RND.sample(range(100), 2)) for c in range(5)}
>>> d
{(17, 53), (74, 5), (88, 11), (21, 56), (15, 78)}
>>> type(d)
<class 'set'>
>>> a = (15, 78)
>>> a in d
True
>>> b = (32, 6)
>>> b in d
False
>>> d.add((4, 1))
>>> d
{(74, 5), (15, 78), (17, 53), (88, 11), (4, 1), (21, 56)}
To your specific question: You are iterating over your tuple_list with a variable called tuple. That's what you should use to compare against:
last_tuple = tuple_list[-1]
for tuple in tuple_list[:-1]:
if tuple.position == last_tuple.position:
tuple_list.remove(tuple)
Except you should not do that at all, because you're doing all kinds of extra work. Instead, maintain a set in parallel with your tuple list, and use the set to determine whether you have seen the position before.
(This assumes your list is hundreds or thousands of elements long. If you're only tracking three or four positions, you could just lsearch the list.)
generic_list = []
positions_seen = set(generic_list)
# blah blah blah code
if left_mouse:
pos = (mouse_position_x, mouse_position_y)
if pos not in positions_seen:
positions_seen.add(pos)
generic_list.append(pos)
If order doesn't matter, you could use a set. It'll keep only unique tuple in your list. Then you can create a new list from this set if needed. For example:
generic_list = [(1,2), (3,4), (1,2), (5,6)]
generic_list = set(generic_list) # {(1, 2), (3, 4), (5, 6)}
generic_list = list(generic_list) # [(1, 2), (5, 6), (3, 4)]

How can I get the cartesian product of lists that are values in a dictionary? [duplicate]

This question already has answers here:
How to get the cartesian product of multiple lists
(17 answers)
Closed 8 months ago.
I have a dictionary:
mydict = {'item1':[1,2,3],'item2':[10,20,30]}
I want to create the cartesian product of the two so that I get a tuple of each possible pair.
output: [(1,10),(1,20),(1,30),
(2,10),(2,20),(2,30),
(3,10),(3,20),(3,30)]
It seems like there would be a simple way to do this so that it extends if I have three items. Kind of like a dynamic number of loops. Feels like I am missing an obvious way to do this...
The itertools.product() function will do this:
>>> import itertools
>>> mydict = {'item1':[1,2,3],'item2':[10,20,30]}
>>> list(itertools.product(*mydict.values()))
[(10, 1), (10, 2), (10, 3), (20, 1), (20, 2), (20, 3), (30, 1), (30, 2), (30, 3)]
If you need to control the order of the resulting tuples, you can do
itertools.product(mydict['item1'], mydict['item2'])
You can also brute force it using two loops
mydict = {'item1':[1,2,3],'item2':[10,20,30]}
x = []
for i in mydict['item1']:
for j in mydict['item2']:
x.append((i,j))
All this code does is go through all of the item in mydict['item1'], then through each item in mydict['item2'], then appends a pair of each to a new list.
It will give you this result:
[(1, 10), (1, 20), (1, 30), (2, 10), (2, 20), (2, 30), (3, 10), (3, 20), (3, 30)]
You can use List Comprehensions:
[(i, j) for i in mydict['item1'] for j in mydict['item2']]
you could do two for loops.
- the first one would keep track of the index position of the first item list.
-The second loop would go through each item in the second.
- After it runs through all the items, the first for loop would increment to the next item in its list and the second loop will run through the second list again, etc.

Sort dict of tuples by either tuple value with customised comparator

I'm working on some python dicts of tuples. Each tuple containing 2 ints. The first digit in the tuple is reffered to as value and the second digit is referred to as work. I have 3 different comparators and I need to sort the dicts into descending order. This order should be determined by which comparator is called. i.e. the dict can be sorted 3 different ways. I've tried as many different ways as I could find to get this to work. I can do it without using the comparator by just breaking it up into a list and sorting by slicing the tuples but if anyone can shed some light on the syntax to sort using the comparators it would be greatly appreciated. Mine seems to be returning correctly for cmpWork but the other 2 aren't reversed.
Also it would be great if I could get the dict sorted by the tuple values.
I got a sort working with
sortedSubjects = sorted(tmpSubjects.iteritems(), key = operator.itemgetter(1), reverse = True)
but this doesn't let me slice the tuples.
First time posting noob so apologies for any mistakes.
def cmpValue(subInfo1, subInfo2):
return cmp(subInfo2[0] , subInfo1[0])
def cmpWork(subInfo1, subInfo2):
return cmp(subInfo1[1] , subInfo2[1])
def cmpRatio(subInfo1, subInfo2):
return cmp((float(subInfo2[0]) / subInfo2[1]) , (float(subInfo1[0]) / subInfo1[1]))
def greedyAdvisor(subjects, comparator):
tmpSubjects = subjects.copy()
sortedSubjects = sorted(tmpSubjects.values(), comparator, reverse = True)
print sortedSubjects
smallCatalog = {'6.00': (16, 8),'1.00': (7, 7),'6.01': (5, 3),'15.01': (9, 6)}
greedyAdvisor(smallCatalog, cmpRatio)
greedyAdvisor(smallCatalog, cmpValue)
greedyAdvisor(smallCatalog, cmpWork)
[(7, 7), (9, 6), (5, 3), (16, 8)]
[(5, 3), (7, 7), (9, 6), (16, 8)]
[(16, 8), (7, 7), (9, 6), (5, 3)]
ps
The line
sortedSubjects = sorted(tmpSubjects.iteritems(), key = operator.itemgetter(1), reverse = True)
returns
[('6.00', (16, 8)), ('15.01', (9, 6)), ('1.00', (7, 7)), ('6.01', (5, 3))]
which is almost exactly what I'm looking for except that I can't sort by the second value in the tuple and I can't sort by cmpRatio either.
but this doesn't let me slice the tuples
Starting with your example:
sortedSubjects = sorted(tmpSubjects.iteritems(),
key=operator.itemgetter(1),
cmp=comparator, # What about specifying the comparison?
reverse=True)
If you need to sort dictionary - use collections.OrderedDict
E.g., sort by 1st element of tuple
OrderedDict(sorted(smallCatalog.items(), key=lambda e:e[1][0]))
Out[109]: OrderedDict([('6.01', (5, 3)), ('1.00', (7, 7)), ('15.01', (9, 6)), ('6.00', (16, 8))])

Categories