Sorting a list of lists in Python - python

c2=[]
row1=[1,22,53]
row2=[14,25,46]
row3=[7,8,9]
c2.append(row2)
c2.append(row1)
c2.append(row3)
c2 is now:
[[14, 25, 46], [1, 22, 53], [7, 8, 9]]
how do i sort c2 in such a way that for example:
for row in c2:
sort on row[2]
the result would be:
[[7,8,9],[14,25,46],[1,22,53]]
the other question is how do i first sort by row[2] and within that set by row[1]

The key argument to sort specifies a function of one argument that is used to extract a comparison key from each list element. So we can create a simple lambda that returns the last element from each row to be used in the sort:
c2.sort(key = lambda row: row[2])
A lambda is a simple anonymous function. It's handy when you want to create a simple single use function like this. The equivalent code not using a lambda would be:
def sort_key(row):
return row[2]
c2.sort(key = sort_key)
If you want to sort on more entries, just make the key function return a tuple containing the values you wish to sort on in order of importance. For example:
c2.sort(key = lambda row: (row[2],row[1]))
or:
c2.sort(key = lambda row: (row[2],row[1],row[0]))

>>> import operator
>>> c2 = [[14, 25, 46], [1, 22, 53], [7, 8, 9]]
>>> c2.sort(key=itemgetter(2))
>>> c2
[[7, 8, 9], [14, 25, 46], [1, 22, 53]]

Well, your desired example seems to indicate that you want to sort by the last index in the list, which could be done with this:
sorted_c2 = sorted(c2, lambda l1, l2: l1[-1] - l2[-1])

Related

Comparing lists and extracting unique values

I have two lists:
l1: 38510 entries
l2: 6384 entries
I want to extract only values, which are present in both lists.
So far that was my approach:
equals = []
for quote in l2:
for quote2 in l1:
if quote == quote2:
equals.append(quote)
len(equals)) = 4999
len(set(equals))) = 4452
First of all, I have the feeling this approach is pretty inefficient, because I am checking every value in l1 several times ..
Furthermore, it seems that I get still duplicates. Is this due to the inner-loop for l1?
Thank you!!
You can use list comprehension and the in operator.
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
b = [2, 4, 6, 8, 0]
[x for x in a if x in b]
#[2, 4, 6, 8]
You were on the right track by using sets. One of set's coolest features is that you can get the intersection between two sets. An intersection is another way to say the values that occur in both sets. You can read about it more in the docs
Here is my example:
l1_set = set(l1)
l2_set = set(l2)
equals = l1_set & l2_set
#If you really want it as a list
equals = list(equals)
print(equals)
The & operator tells python to return a new set that only has values in both sets. At the end, I went ahead and converted equals back to a list because that's what your original example wanted. You can omit that if you don't need it.
1. This is the simplest method where we haven’t used any built-in functions.
# Two lists in most simple way of showing the intersection
def intersection(list_one, list_two):
temp_list = [value for value in list_one if value in list_two]
return temp_list
# Illustrate the intersection
list_one = [4, 9, 1, 17, 11, 26, 28, 54, 69]
list_two = [9, 9, 74, 21, 45, 11, 63, 28, 26]
print(intersection(list_one, list_two))
# [123, 3, 23, 15]
2. You can use the python set() method.
# Two lists using set() method
def intersection(list_one, list_two):
return list(set(list_one) & set(list_two))
# Illustrate the intersection
list_one = [15, 13, 123, 23, 31, 10, 3, 311, 738, 25, 124, 19]
list_two = [12, 14, 1, 15, 36, 123, 23, 3, 315, 87]
print(intersection(list_one, list_two))
# [123, 3, 23, 15]
3. In this technique, we can use the built-in function called intersection() to compute the intersected list.
First, we need to use set() for a larger list then compute the intersection.
# Two lists using set() and intersection()
def intersection_list(list_one, list_two):
return list(set(list_one).intersection(list_two))
# Illustrate the intersection
list_one = [15, 13, 123, 23, 31, 10, 3, 311, 738, 25, 124, 19]
list_two = [12, 14, 1, 15, 36, 123, 23, 3, 315, 87, 978, 4, 13, 19, 20, 11]
if len(list_one) < len(list_two):
list_one, list_two = list_two, list_one
print(intersection_list(list_one, list_two))
# [3, 13, 15, 19, 23, 123]
Additional you can follow the bellow tutorials
Geeksforgeeks
docs.python.org
LearnCodingFast
Let's assume that all the entries in both of your lists are integers. If so, computing the intersection between the 2 lists would be more efficient than using list comprehension:
import timeit
l1 = [i for i in range(0, 38510)]
l2 = [i for i in range(0, 6384)]
st1 = timeit.default_timer()
# Using list comprehension
l3 = [i for i in l1 if i in l2]
ed1 = timeit.default_timer()
# Using set
st2 = timeit.default_timer()
l4 = list(set(l1) & set(l2))
ed2 = timeit.default_timer()
print(ed1-st1) # 5.7621682 secs
print(ed2-st2) # 0.004478600000000554 secs
As you have such long lists, you might want to use numpy which is specialized in providing efficient list processing for Python.
You can enjoy the fast processing with its numpy function. For your case, you can use numpy.intersect1d() to get the sorted, unique values that are in both of the input arrays, as follows:
import numpy as np
l1 = [1, 3, 5, 10, 11, 12]
l2 = [2, 3, 4, 10, 12, 14, 16, 18]
l_uniques = np.intersect1d(l1, l2)
print(l_uniques)
[ 3 10 12]
You can keep the resulting list as numpy array for further fast processing or further convert it back to Python list by:
l_uniques2 = l_uniques.tolist()

Given a list of integer numbers and a list of indices how can i use map to add 10 to specific elements in the first list?

I want to map a function only to specific elements in a list; those would be the elements of the indices existent in the indices list. I have tried lots of things similar to what I've written here, below. I am trying to achieve this without using the classic for-loop. *edit: by "classic for-loop" I mean using range ( something like: for i in range(len(list)) )
lista = [123, 456, 1, 0, -2, 13, 15, 29, 47, 48]
index_list = [0, 1, 2, 3]
lista = list( map( lambda x: x + 10 if #some condition here I could not figure out#
\ else x for x in list ) )
print(lista)
#expected output: [133, 466, 11, 10, -2, 13, 15, 29, 47, 48]
I have also tried defining my own function and then mapping it, but to no avail. How can I do this?
Assuming that you don't want to use the straight forward solution by iterating the indices list instead:
The problem is that one of the variables you're depending on (the index) is not included in your call to map. You'll have to insert that into the map call in some way, for example by using enumerate - which will emit a (idx, value) tuple for each element in your list.
nums = [123, 456, 1, 0, -2, 13, 15, 29, 47, 48]
indices = [0, 1, 2, 3]
result = list(
map(
lambda x: x[1] + 10 if x[0] in indices else x[1],
enumerate(nums)
)
)
print(result)
Be aware that the if x[0] in indices part will search the indices list linearly, and will make the whole operation O(n * m). This can be optimised by using a set (which has O(1) lookup as the common case) or a dictionary instead.
> [133, 466, 11, 10, -2, 13, 15, 29, 47, 48]

Is it possible to find the original name of lists put in another list, by interacting with the latter list?

I have a couple lists (raw data from elsewhere), that I collect in another list, to do stuff with later in the code. (So if I were to edit the raw data I am using, I can just change the original lists, edit the everything-list to reflect added/removed lists, and have all the subsequent code reflect those changes without me having to change anything in the rest of the code.)
Like so:
a=[1,2,3]
b=[55,9,18]
c=[15,234,2]
everything=[a,b,c]
At one point I would like to use the NAMES of my original lists ('a','b', and 'c' in my example).
Is there a way for me to use my list 'everything' to access the names of the lists put in it?
(So for the code
for i in range(len(everything)):
print('The data from',???,'is',everything[i])
??? would be replaced by something to ideally print
The data from a is [1, 2, 3]
The data from b is [55, 9, 18]
The data from c is [15, 234, 2]
)
You can use dictionaries for this.
a=[1,2,3]
b=[55,9,18]
c=[15,234,2]
everything={'a':a,'b': b,'c': c}
for i in range(len(everything['a'])):
everything['a'][i] += 10
print(everything)
# >> {'a': [11, 12, 13], 'b': [55, 9, 18], 'c': [15, 234, 2]}
print(a)
# >> [11, 12, 13]
for var, val in everything.items():
print(f'The data from {var} is {val}')
"""
>>The data from a is [11, 12, 13]
The data from b is [55, 9, 18]
The data from c is [15, 234, 2]
"""
There's a way you can do this, but using a dictionary is equivalent to your case as its keys are unique and can be used as your variable name. Hence, with dictionaries you can retrieve values and print them in any format you need:
a = [1,2,3]
b = [55,9,18]
c = [15,234,2]
everything= {'a': a, 'b': b, 'c': c}
for k, v in everything.items():
print(f'The data from {k} is {v}')
If you are trying to access the variable name using id, this can be used.
a=[1,2,3]
b=[55,9,18]
c=[15,234,2]
everything = [a,b,c]
def get_name(your_id):
name = [x for x,_ in globals().items() if id(_)==your_id ]
return(name[0])
for i in range(len(everything)):
print('The data from',get_name(id(everything[i])),'is',everything[i])
This outputs:
('The data from', 'a', 'is', [1, 2, 3])
('The data from', 'b', 'is', [55, 9, 18])
('The data from', 'c', 'is', [15, 234, 2])
globals is a built-in which returns a dict of variables/values in the global name space. So you could get the variable name given the id.

Check if double of element in first list is present in second list and print the output

Suppose
List1 = [ 23, 45, 6, 7, 34]
List2 = [46, 23, 1, 14, 68, 56]
Compare List1 and List2 and print the element of List1 which have a double value in List2
Output = [23,7,34]
Try this:
Output = [i for i in List1 if i*2 in List2]
You can convert list2 to a set for efficient lookups, and use a list comprehension with the said condition for the desired output:
set2 = set(List2)
[i for i in List1 if i * 2 in set2]
You already have the answer but just of the sake of simplicity. Basically you want to iterate through List1 and check if double value is in List2. If so add element to the output array.
List1 = [ 23, 45, 6, 7, 34]
List2 = [46, 23, 1, 7, 14, 68, 56]
output = []
for i in List1:
if i*2 in List2:
output.append(i)
print output
You already got the answers. However, just for fun, I came up with the following method. I did not benchmark all the approaches listed here. It can be fun to do that. This is an interesting question and can be investigated more. However, just for the sake of it I present the solution I did.
import numpy as np
l = np.array(List1) * 2
print(l)
## array([46, 90, 12, 14, 68])
print(set(l) & set(List2))
## {68, 46, 14}
l2 = set(l) & set(List2)
print([List1[list(np.nonzero(l == i))[0][0]] for i in l if i in l2])
## [23, 7, 34]
It uses the broadcasting of numpy along with the fast intersection operation of Python set. This maybe useful if the two lists are very big.

Removing duplicates in list of lists

I have a list consisting of lists, and each sublist has 4 items(integers and floats) in it. My problem is that I want to remove those sublists whose index=1 and index=3 match with other sublists.
[[1, 2, 0, 50], [2, 19, 0, 25], [3, 12, 25, 0], [4, 18, 50, 50], [6, 19, 50, 67.45618854993529], [7, 4, 50, 49.49657024231138], [8, 12, 50, 41.65340802385248], [9, 12, 50, 47.80600357035001], [10, 18, 50, 47.80600357035001], [11, 18, 50, 53.222014760339356], [12, 18, 50, 55.667812693447615], [13, 12, 50, 41.65340802385248], [14, 12, 50, 47.80600357035001], [15, 13, 50, 47.80600357035001], [16, 3, 50, 49.49657024231138], [17, 3, 50, 49.49657024231138], [18, 4, 50, 49.49657024231138], [19, 5, 50, 49.49657024231138]]
For example,[7, 4, 50, 49.49657024231138] and [18, 4, 50, 49.49657024231138] have the same integers at index 1 and 3. So I want to remove one, which one doesn't matter.
I have looked at codes which allow me to do this on the basis of single index.
def unique_items(L):
found = set()
for item in L:
if item[1] not in found:
yield item
found.add(item[1])
I have been using this code which allows me to remove lists but only on the basis of a single index.(I haven't really understood the code completely.But it is working.)
Hence, the problem is removing sublists only on the basis of duplicate values of index=1 and index=3 in the list of lists.
If you need to compare (item[1], item[3]), use a tuple. Tuple is hashable type, so it can be used as a set member or dict key.
def unique_items(L):
found = set()
for item in L:
key = (item[1], item[3]) # use tuple as key
if key not in found:
yield item
found.add(key)
This is how you could make it work:
def unique_items(L):
# Build a set to keep track of all the indices we've found so far
found = set()
for item in L:
# Now check if the 2nd and 4th index of the current item already are in the set
if (item[1], item[3]) not in found:
# if it's new, then add its 2nd and 4th index as a tuple to our set
found.add((item[1], item[3])
# and give back the current item
# (I find this order more logical, but it doesn't matter much)
yield item
This should work:
from pprint import pprint
d = {}
for sublist in lists:
k = str(sublist[1]) + ',' + str(sublist[3])
if k not in d:
d[k] = sublist
pprint(d.values())

Categories

Resources