substracting elements of a dictionary - python

I have a dictionary made up of lists:
>>> triplets.get(k)
[[1, 3, 15], [1, 3, 13], [1, 3, 11], [1, 3, 9], [1, 3, 8], [1, 3, 5], [1, 4, 15]
and also dictionaries:
>>> cset1.get(k)
[set([5])]
>>> cset2.get(k)
[[1, 8], [1, 9], [1, 11]]
I want to delete elements of triplets which contain the element of cset1 or both elements of cset2, i.e. I want to delete [1,3,5] which contains [5] and also [1, 3, 8], [1, 3, 9], [1, 3, 11] which contain both elements of cset2.
I have the following piece of code (which doesn't do anything at all):
CDln = len(triplets.get(k))
for ii in range(CDln):
if cset1.get(k) in triplets.get(k)[ii] or cset2.get(k) in triplets.get(k)[ii]:
print "delete element of triplets in location:", ii
I cannot figure out how to delete those elements from dictionary triplets (I use the print statement as a dummy of what I want).

I am not quite sure if I got you right, but take a look and comment please:
k = 42 #whatever
triplets = {k: [[1, 3, 15], [1, 3, 13], [1, 3, 11], [1, 3, 9], [1, 3, 8], [1, 3, 5], [1, 4, 15]]}
cset1 = {k: [set([5])]}
cset2 = {k: [{1, 8}, {1, 9}, {1, 11}]} #changed this to sets
triplets[k] = [x for x in triplets[k] if
all (y - set(x) for y in cset1[k]) and
all (y - set(x) for y in cset2[k])
]
print(triplets[k])

I'm not sure what ii is, but I think this is what you want.
b = cset1[k]
c = cset2[k]
triplets[k] = filter(
lambda lst:
any(lambda x: x in b, lst) or
any(lambda c1: all(lambda x: x in c1), c),
triplets[k]
]
But:
I wonder why you have a cset1 and cset2. It seems as though, you should just have cset2, whose value is
[[5], [1, 8], [1, 9], [1, 11]]

Related

manipulate list of list using random and restrictions

I have two lists a and b.
a=[[3, 1], [3, 2, 3], [5, 1, 4, 8], [3, 5], [10, 1, 3, 6, 7],[2,1,2]]
b=[[4], [3], [9], [5], [21],[5]]
List of list a is interpreted as follows.
a[0]=[3,1]. This means I want 3 items, where item 1 must be included.
a[-1]=[2,1,2] I want 2 items, where item 1 and item 2 must
be included.
a[2] = [5,1,4,8] I want 5 items, where item 1, item 4 and item 8 must be included.
List of list b is the available list of item from which list a can take from.
b[0]=[4] this means item 1, item 2, item 3 and item 4 is available. This is linked
to a[0]
b[-1]=[5] item 1, item 2, item 3, item 4 and item 5 is available. This is linked to a[-1]
b[2]=[9] this means i have 9 items is available. This is linked to a[2]
I'm trying to create a new list of list c such that it produces the following result.
For a[0]=[3,1] and b[0]=[4] it should produce the following result [1,2,4]
For a[-1]=[2,1,2] and b[-1]=[5] it should produce [1,2]
For a[2] = [5,1,4,8] and b[2]=[9] should produce [1,4,8,3,9]
What I have tried so far:
import random
a=[[3, 1], [3, 2, 3], [5, 1, 4, 8], [3, 5], [10, 1, 3, 6, 7],[2,1,2]]
b=[[4], [3], [9], [5], [21],[5]]
c=[sorted(random.sample(range(1, j[0]+1), int(i[0]))) for i,j in zip(a,b)]
print(c) # produces [[1, 3, 4], [1, 2, 3], [1, 3, 4, 6, 9], [1, 4, 5], [2, 5, 6, 7, 13, 15, 16, 19, 20, 21], [3, 4]]
As you can see, list c does not take into account those restrictions that I need.
Desired output will look something like this.
c= [[1,2,4],[2,3,1],[1,4,8,3,9],[5,1,3],[1,3,6,7,2,5,9,10,20,21],[1,2]]
You can run a loop over the two lists and construct a remaining_items list to randomly sample from -
c = []
for constraints, items in zip(a, b):
num_items, *required_items = constraints
pick_list = list(_ for _ in range(1, items[0] + 1) if _ not in required_items)
num_items_to_pick = num_items - len(required_items)
remaining_items = random.sample(pick_list, num_items_to_pick)
print(required_items + remaining_items)
c.append(required_items + remaining_items)
Output
[[1, 2, 3],
[2, 3, 1],
[1, 4, 8, 3, 6],
[5, 3, 1],
[1, 3, 6, 7, 18, 2, 14, 21, 19, 15],
[1, 2]]

Split a NumPy array into subarrays according to the values (not sorted, but grouped) of another array

Suppose I have two NumPy arrays
x = [[1, 2, 8],
[2, 9, 1],
[3, 8, 9],
[4, 3, 5],
[5, 2, 3],
[6, 4, 7],
[7, 2, 3],
[8, 2, 2],
[9, 5, 3],
[10, 2, 3],
[11, 2, 4]]
y = [0, 0, 1, 0, 1, 1, 2, 2, 2, 0, 0]
Note:
(values in x are not sorted in any way. I chose this example to better illustrate the example)
(These are just two examples of x and y. values of x and y can be arbitrarily many different numbers and y can have arbitrarily different numbers, but there are always as many values in x as there are in y)
I want to efficiently split the array x into sub-arrays according to the values in y.
My desired outputs would be
z_0 = [[1, 2, 8],
[2, 9, 1],
[4, 3, 5],
[10, 2, 3],
[11, 2, 4]]
z_1 = [[3, 8, 9],
[5, 2, 3],
[6, 4, 7],]
z_2 = [[7, 2, 3],
[8, 2, 2],
[9, 5, 3]]
Assuming that y starts with zero and is not sorted but grouped, what is the most efficient way to do this?
Note: This question is the unsorted version of this question:
Split a NumPy array into subarrays according to the values (sorted in ascending order) of another array
One way to solve this is to build up a list of filter indexes for each y value and then simply select those elements of x. For example:
z_0 = x[[i for i, v in enumerate(y) if v == 0]]
z_1 = x[[i for i, v in enumerate(y) if v == 1]]
z_2 = x[[i for i, v in enumerate(y) if v == 2]]
Output
array([[ 1, 2, 8],
[ 2, 9, 1],
[ 4, 3, 5],
[10, 2, 3],
[11, 2, 4]])
array([[3, 8, 9],
[5, 2, 3],
[6, 4, 7]])
array([[7, 2, 3],
[8, 2, 2],
[9, 5, 3]])
If you want to be more generic and support different sets of numbers in y, you could use a comprehension to produce a list of arrays e.g.
z = [x[[i for i, v in enumerate(y) if v == m]] for m in set(y)]
Output:
[array([[ 1, 2, 8],
[ 2, 9, 1],
[ 4, 3, 5],
[10, 2, 3],
[11, 2, 4]]),
array([[3, 8, 9],
[5, 2, 3],
[6, 4, 7]]),
array([[7, 2, 3],
[8, 2, 2],
[9, 5, 3]])]
If y is also an np.array and the same length as x you can simplify this to use boolean indexing:
z = [x[y==m] for m in set(y)]
Output is the same as above.
Just use list comprehension and boolean indexing
x = np.array(x)
y = np.array(y)
z = [x[y == i] for i in range(y.max() + 1)]
z
Out[]:
[array([[ 1, 2, 8],
[ 2, 9, 1],
[ 4, 3, 5],
[10, 2, 3],
[11, 2, 4]]),
array([[3, 8, 9],
[5, 2, 3],
[6, 4, 7]]),
array([[7, 2, 3],
[8, 2, 2],
[9, 5, 3]])]
Slight variation.
from operator import itemgetter
label = itemgetter(1)
Associate the implied information with the label ... (index,label)
y1 = [thing for thing in enumerate(y)]
Sort on the label
y1.sort(key=label)
Group by label and construct the results
import itertools
d = {}
for key,group in itertools.groupby(y1,label):
d[f'z{key}'] = [x[i] for i,k in group]
Pandas solution:
>>> import pandas as pd
>>> >>> df = pd.DataFrame({'points':[thing for thing in x],'cat':y})
>>> z = df.groupby('cat').agg(list)
>>> z
points
cat
0 [[1, 2, 8], [2, 9, 1], [4, 3, 5], [10, 2, 3], ...
1 [[3, 8, 9], [5, 2, 3], [6, 4, 7]]
2 [[7, 2, 3], [8, 2, 2], [9, 5, 3]]

How to sort 2D list elements in python?

I need to know how to sort the list elements in python without changing their position.
a = [[5, 4, 5], [4, 5, 6], [2, 8, 2], [5, 2, 2]]
b = [[3, 2, 4], [3, 6, 7], [3, 6, 0], [7, 2, 1]]
c = [[x + y for x, y in zip(s1, s2)] for s1, s2 in zip(a, b)]
c.sort(key=lambda x: x[1])
c.reverse()
for c in c:
print(c)
I tried using the lambda but it sorts them by the first number, thus changing the order.
I need to sort array c so it would look something like this:
Input: c = [[5, 4, 5], [4, 5, 6], [2, 8, 2], [5, 2, 2]]
Output: c = [[4, 5, 5], [4, 5, 6], [2, 2, 8], [2, 2, 5]]
I hope i made myself clear enough, any help is appreciated
You can do this in your original list comprehension using sorted on the inner list comprehension.
>>> [sorted(i+j for i, j in zip(s1, s2)) for s1, s2 in zip(a, b)]
[[6, 8, 9], [7, 11, 13], [2, 5, 14], [3, 4, 12]]
for item in a:
item.sort()
You could try this:
c = [sorted(x) for x in a]

Sort list of lists by min/max in Python

I apologize for a simple question, but I cannot find an answer to it in the archives.
what should i do to sort smaller lists within a larger list.
for example
lst=[[1, 2, 3, 4], [5,9,8,7], [9, 0, 1, 2, 3 ]]
should return
[1, 2, 3, 4]
[5,7,8,9]
[ 0, 1, 2, 3,9 ]
I tried to use lambda
lst.sort(key=lambda x: x.min())
and sorted
lst.sort(key=lambda x: sorted(x))
but neither works. could you please direct me a little bit. Thanks for your guidance.
Keep it simple, just use a list comprehension and sort the list inside the list:
Output:
[[1, 2, 3, 4], [5, 7, 8, 9], [0, 1, 2, 3, 9]]
So, with respect to your code, you can just do this:
lst = [sorted(x) for x in lst]
You can use a list comprehension to sort each sublist, then assign back to your main list
>>> lst = [sorted(i) for i in lst]
>>> lst
[[1, 2, 3, 4], [5, 7, 8, 9], [0, 1, 2, 3, 9]]
You could try something like this:
lst=[[1, 2, 3, 4], [5,9,8,7], [9, 0, 1, 2, 3 ]]
for x in lst:
x.sort()
I looped through lst and sorted each inner list.
You can do this:
>>> list(map(sorted, lst))
[[1, 2, 3, 4], [5, 7, 8, 9], [0, 1, 2, 3, 9]]
If you want to sort in place, you can do something like this:
any(ll.sort() for ll in lst)
(any is really only there to ditch the return values, which are all None; it will return false.)
You can write a function:
def sort_lst(lst):
lists = []
for l in lists:
l = l[:]
l.sort()
lists.append(l)
return lists
or
l = [[1, 2, 3, 6], [1, 2, 5, 6]]
l.sort(key=lambda x: x.sort())
print(l)
Output: [[1, 2, 3, 6], [1, 2, 5, 6]]

Remove a sublist from a list in which the numbers alreadys exist in another sublist

Given a list t:
[[0, 4], [0, 4, 5, 7], [1, 2, 3, 6], [1, 3], [2, 6], [5, 7]]
I want to remove sublists in t, e.g. [0,4], both numbers in which already exist in [0,4,5,7], I want to keep the larger groups and remove smaller groups. And so in the end [[0, 4, 5, 7], [1,2,3,6]] will be my final results.
I have tried the following code but don’t know what is wrong:
V=0
while V<60:
for o in t:
for p in t:
if o!= p:
for s in range(len(o)):
w=[]
if o[s] in p:
w.append(o[s])
#print w
if w==o:
t.remove(w)
V=V+1
print t
You could use sets for this:
lists = [[0, 4], [0, 4, 5, 7], [1, 2, 3, 6], [1, 3], [2, 6], [5, 7]]
sets = map(set, lists)
ret = []
for l in lists:
if not any(set(l) < s for s in sets):
ret.append(l)
print ret
Here, set(l) < s checks that the list l is a proper subset of s.
Or, if you like conciseness:
sets = map(set, lists)
ret = [l for l in lists if not any(set(l) < s for s in sets)]
print ret
l = [[0, 4], [0, 4, 5, 7], [1, 2, 3, 6], [1, 3], [2, 6], [5, 7]]
final = l[:]
for m in l:
for n in l:
if set(m).issubset(set(n)) and m != n:
final.remove(m)
break
print final
output:
[[0, 4, 5, 7], [1, 2, 3, 6]]

Categories

Resources