Django queryset to list of ids with integer values - python

I need to retrieve IDs from multiple queries and add them into a list.
products = Product.objects.filter(category="Apple").values_list("product_id", flat=True)
reviewed = Reviews.objects.filter(category="Apple").values_list("product_id", flat=True)
selected_ids = [10,20,30]
Then I tried
all_products = selected_ids + products + reviewed
This raised error as list cannot be added to queryset.
so, I tried,
all_product_ids = selected_ids + list(products) + list(reviewed)
This works but, all_products has a mix of int and tuple values [10, 20, 30, (2,), (2,), (1,)]
I need them to be [10, 20, 30, 2, 2, 1]

You can use union and then add them with the list:
qset_ids = Product.objects.filter(category="Apple").values_list("product_id").union(Reviews.objects.filter(category="Apple").values_list("product_id"))
all_product_ids = selected_ids + list(qset_ids.values_list('product_id',flat=True))

Related

Python: Add four lists to a dictionary that already has keys, all lists/dict have same length of values

I have 5 lists:
periods = []
interface_sum = []
intraslab_sum = []
crustal_sum = []
total_sums = []
I want to make the periods list as the key, then have the rest of those lists appended onto the periods key. Here is what the data looks like:
So from this pic, I want the top list that says like 0.001, 0.1, 0.2, etc to be the keys, then I want the four lists below that to be appended to their respective key. So like it would be:
data = {'0.001':[16.36,35.45,48.15,99.96], '0.1':[11.10,43.40,45.49,99.99], etc}
Any ideas on how to get this done? Thanks.
The simplest case would be to use zip twice; once for the values and again for key-value pairs and use the dict constructor:
out = dict(zip(periods, zip(interface_sum, intraslab_sum, crustal_sum, total_sums)))
For example, if:
periods = [1,2,3]
interface_sum = [4,5,6]
intraslab_sum = [7,8,9]
crustal_sum = [10,11,12]
total_sums = [13,14,15]
Then output:
{1: (4, 7, 10, 13), 2: (5, 8, 11, 14), 3: (6, 9, 12, 15)}
As you can see it creates tuples as values. If you want them as lists, you can do so by mapping them:
out = dict(zip(periods, map(list, zip(interface_sum, intraslab_sum, crustal_sum, total_sums))))
or use a dict comprehension:
out = {k: list(v) for k,v in zip(periods, zip(interface_sum, intraslab_sum, crustal_sum, total_sums))}

how to return the order index of each element of a list? [duplicate]

This question already has answers here:
Rank items in an array using Python/NumPy, without sorting array twice
(11 answers)
Closed 4 years ago.
I have a list of Numbers, say L=[50, 10, 30], and in Python I want to return a list giving the order index of each element in L, which would be this output: [2, 0, 1].
Though it seems to be a simple task, many questions on this site (here here and here for instance) focus on the other way round, meaning the index from the sorted list point of view: [1, 2, 0], which is not what I want.
Thanks,
EDIT: about repetitions, i'd like them to be counted as well (draws taken in order of appearance). [50,30,10,30] would give [3,1,0,2]
One liner:
l = [50, 30, 10, 30]
numpy.argsort(numpy.argsort(l))
# array([3, 1, 0, 2])
it is the index list of the sorted order:
def sort_order(lst):
orders = sorted(list(range(len(lst))), key=lambda x: lst[x])
ret = [0] * len(lst)
for i in range(len(ret)):
ret[orders[i]] = i
return ret
print(sort_order([50, 10, 30]) # [2,0,1]
Enumerating and sorting twice like:
L = [50, 10, 30]
x = tuple(k[1] for k in sorted((x[1], j) for j, x in enumerate(
sorted((x, i) for i, x in enumerate(L)))))
print(x)
Results:
(2, 0, 1)
Using dicts..
L = [50, 10, 30, 10, 30]
d = {counter:value for counter,value in enumerate(L)} #L is your list
sorteddict = sorted(d.items(), key=lambda x: x[1])
d2 = {counter:value for counter,value in enumerate(sorteddict)}
order_index = {d2[i][0]:i for i in d2}
print(order_index.values())

Combine elements within list of lists python

I have a list of the form
in_list = [[10, 15], [16,21], [22,25], [26,30], [35,40], [45,50],[51,55]]
And I need to combine consecutive lists that contain consecutive integers in the last and first position into lists. So
if in[1][0] = in[0][1] + 1:
out[0] = [in[0][0],in[1][1]]
The output will be of the form of
out_list = [[10,30], [35, 40], [45,55]]
Right now, the code I have does multiple iterations on the out list and combines the elements, continuing till the number of elements in the list stops changing after an iteration. How can I achieve this in a more pythonic way?
This should do the trick
out = [inp[0]]
for l in inp[1:]:
if l[0] == out[-1][1] + 1:
out[-1][1] = l[1]
else:
out.append(l)
Did you mean one-line stuff using numpy? :)
Try the following shortcut:
import numpy as np
# data is of shape (n,2), n=6
data = np.array([[10, 15], [16,21], [22,25], [26,30], [35,40], [45,50],[51,55]])
# seek for consecutive numbers
marks = (data[:-1,1]+ 1) == data[1:,0]
# re-arrange and return to python lists
output = np.stack([data[:-1,0][marks],data[1:,1][marks]],axis=1).tolist()
EDIT:
Another option using lists:
data = [[10, 15], [16,21], [22,25], [26,30], [35,40], [45,50],[51,55]]
mylist = []
def func(x1,x2):
if x1[1] +1 == x2[0]:
mylist.append((x1[0],x2[1]))
list(map(func,data[:-1],data[1:]))
print(mylist)
Output:
[(10, 21), (16, 25), (22, 30), (45, 55)]

pop from list using index list

list1 = [1,2,5,6,7,8,10,41,69,78,83,100,105,171]
index_list = [0,4,7,9,10]
how do I pop an item from list1 using indexes from index_list?
output_list = [2,5,6,8,10,69,100,105,17]
How about the opposite: Retain those elements that are not in the list:
>>> list1 = [1,2,5,6,7,8,10,41,69,78,83,100,105,171]
>>> index_list = [0,4,7,9,10]
>>> index_set = set(index_list) # optional but faster
>>> [x for i, x in enumerate(list1) if i not in index_set]
[2, 5, 6, 8, 10, 69, 100, 105, 171]
Note: This does not modify the existing list but creates a new one.
list1 = [1,2,5,6,7,8,10,41,69,78,83,100,105,171]
index_list = [0,4,7,9,10]
print([ t[1] for t in enumerate(list1) if t[0] not in index_list])
RESULT
[2, 5, 6, 8, 10, 69, 100, 105, 171]
enumerate will create a structure like below.
[(0, 1), (1, 2),(2, 5),(3, 6),(4, 7),(5, 8),...(13, 171)]
Where t = (0,1) (index,item)
t[0] = index
t[1] = item
You could try this -
for index in sorted(index_list, reverse=True):
list1.pop(index)
print (list1)
pop() has an optional argument index. It will remove the element in index
Use list.remove(item)
for n in reversed(index_list):
list1.remove(list1[n])
or list.pop(index)
for n in reversed(index_list):
list1.pop(n)
Both methods are described here https://docs.python.org/2/tutorial/datastructures.html
Use reversed() on your index_list (assuming that the indices are always ordered like in the case you have shown), so you remove items from the end of the list and it should work fine.

List intersection in Django ORM how to?

Let's say, I have two tables: all_my_friends_ids and my_facebook_friends_ids which represent two lists of my friends in database:
all_my_friends_ids = self.user.follows.values_list('pk', flat=True)
(e.g. all_my_friends_ids = [1, 4, 9, 16, 18, 20, 24, 70])
my_facebook_friends_ids = User.objects.filter(facebook_uid__in=my_facebook_friends_uids)
(e.g. my_facebook_friends_ids = [4, 16, 28, 44, 39])
I want to check if all elements of my_facebook_friends_ids list have entry in all_my_friends_ids or not, and if not - return id elements that are not in the all_my_friends_ids list (and add them later in all_my_friends_ids).
How to solve this task in Django ORM with QuerySet? I tried to extract ids and apply this function to them:
def sublistExists(list1, list2):
return ''.join(map(str, list2)) in ''.join(map(str, list1))
but it doesn't seem the right way, especially for my case.
facebook_exclusives = (User.objects
.filter(facebook_uid__in=my_facebook_friends_uids)
.exclude(facebook_uid__in=all_my_friends_ids))
If you want, you can offload it to your database completely, without creating a (potentially huge) intermediate list in Python:
facebook_exclusives = (User.objects
.filter(facebook_uid__in=my_facebook_friends_uids)
.exclude(facebook_uid__in=self.user.follows.all()))

Categories

Resources