Reordering elements of lists in a list of lists - python

I have a list of lists composed of elements that are strings and integers, e.g.
a = [['i','j',1,2,3...n], ['k','l',4,5,6...n], ['m','n',7,8,9...n]]
I would like to reorder the string elements in each sub list such that a[l][1] takes the place of a[l][0] and vice versa, so I end up with:
a = [['j','i',1,2,3...n], ['l','k',4,5,6...n], ['n','m',7,8,9...n]]
I have tried iterating through each sub list and using an order variable to change the integer positions, but it does not seem to change the ordering in each list:
order = [1,0,2,3,4...n]
for l in reversed(range(len(a))):
[a[l][j] for j in order]
What am I doing wrong?

[a[l][j] for j in order]
This is just an expression that is evaluated and then discarded.
If you want to change a, you need to assign to it:
a[l] = [a[l][j] for j in order]

The simplest for the concrete issue would be slice assignment in a loop:
for sub in a:
sub[:2] = reversed(sub[:2])
With your general order approach, you could do:
for sub in a:
sub[:] = [sub[i] for i in order] # needs to mutate the actual object!

just use this code:
a[1][1], a[1][0] = a[1][0] , a[1][1]
thanks to python

Related

Find indexes of common items in two python lists

I have two lists in python list_A and list_B and I want to find the common item they share. My code to do so is the following:
both = []
for i in list_A:
for j in list_B:
if i == j:
both.append(i)
The list common in the end contains the common items. However, I want also to return the indexes of those elements in the initial two lists. How can I do so?
It is advised in python that you avoid as much as possible to use for loops if better methods are available. You can efficiently find the common elements in the two lists by using python set as follows
both = set(list_A).intersection(list_B)
Then you can find the indices using the build-in index method
indices_A = [list_A.index(x) for x in both]
indices_B = [list_B.index(x) for x in both]
Instead of iterating through the list, access elements by index:
both = []
for i in range(len(list_A)):
for j in range(len(list_B)):
if list_A[i] == list_B[j]:
both.append((i,j))
Here i and j will take integer values and you can check values in list_A and list_B by index.
You can also get common elements and their indexes with numpy.intersect1d()
common_elements, a_indexes, b_indexes = np.intersect1d(a, b, return_indices=True)

remove tuples with only one item -- python

I have a list of tuples and some of the tuples only have one item in it. How do I remove tuples with only one item from the list? I want to keep tuples with two items in it.
The tuples I have contain a string, and then an integer after it
list = ((['text'],1),(['text'],2),((3,))
I may suggest:
filtered_list = [tup for tup in list if len(tup) == 2]
You can also check if tuple length is higher than one or anything else...
What about:
new_list = [x for x in old_list if len(x) > 1]
You want to create a list with squared brackets instead of parentheses, otherwise you'd create a tuple.
Also please don't call your variables like built-in names as EdChum suggested.
The solution here is to filter your list:
l=[(1,2),(3,),(4,5)]
filter(lambda x: len(x)!=1, l)
You could use something like that to rebuild a new tuple with tuple that have a length greater than 1.
new_list = tuple(item for item in your_list if len(item) > 1)

Exclude items from list of lists Python

I have the next list of
testList = []
testList.append([0,-10])
testList.append([-12,122])
testList.append([13,172])
testList.append([17,296])
testList.append([-10,80])
testList.append([-16,230])
testList.append([-18, 296])
testList.append([-2, -8])
testList.append([-5,10])
testList.append([2,-4])
and another lists which contains elements from previous list:
m1 = []
m1.append([0, -10])
m1.append([13, 172])
Then I try to get a subarray from the list testList with the next statement:
[element for i, element in enumerate(testList) if i not in m1]
But I get the same list as testList.
How can I achieve this?
If you don't care about the order in the lists, you can use sets instead:
# result will be a set, not a list
not_in_testlist = set(testlist) - set(m1)
If you want the result to be a list again:
# result will be a list with a new order
not_in_m1 = list(set(testlist) - set(m1))
Be aware that using sets will lose the order of the original lists because sets are unordered types (they use hashing under the hood).
If you need to preserve the order, then Andrew Allaire's answer is correct:
# result is a list, order is preserved
not_in_testlist = [e for e in testlist if e not in m1]
The problem is with your use of enumerate. The i is just going to be an integer, and therefor never in a list that only has lists in it. Try this:
[element for element in testList if element not in m1]
Try with this:
def clean_list(my_list, exclusion_list):
new_list = []
for i in my_list:
if i in exclusion_list:
continue
else:
new_list.append(i)
return new_list

python list.iteritems replacement

I've got a list in which some items shall be moved into a separate list (by a comparator function). Those elements are pure dicts. The question is how should I iterate over such list.
When iterating the simplest way, for element in mylist, then I don't know the index of the element. There's no .iteritems() methods for lists, which could be useful here. So I've tried to use for index in range(len(mylist)):, which [1] seems over-complicated as for python and [2] does not satisfy me, since range(len()) is calculated once in the beginning and if I remove an element from the list during iteration, I'll get IndexError: list index out of range.
Finally, my question is - how should I iterate over a python list, to be able to remove elements from the list (using a comparator function and put them in another list)?
You can use enumerate function and make a temporary copy of the list:
for i, value in enumerate(old_list[:]):
# i == index
# value == dictionary
# you can safely remove from old_list because we are iterating over copy
Creating a new list really isn't much of a problem compared to removing items from the old one. Similarly, iterating twice is a very minor performance hit, probably swamped by other factors. Unless you have a very good reason to do otherwise, backed by profiling your code, I'd recommend iterating twice and building two new lists:
from itertools import ifilter, ifilterfalse
l1 = list(ifilter(condition, l))
l2 = list(ifilterfalse(condition, l))
You can slice-assign the contents of one of the new lists into the original if you want:
l[:] = l1
If you're absolutely sure you want a 1-pass solution, and you're absolutely sure you want to modify the original list in place instead of creating a copy, the following avoids quadratic performance hits from popping from the middle of a list:
j = 0
l2 = []
for i in range(len(l)):
if condition(l[i]):
l[j] = l[i]
j += 1
else:
l2.append(l[i])
del l[j:]
We move each element of the list directly to its final position without wasting time shifting elements that don't really need to be shifted. We could use for item in l if we wanted, and it'd probably be a bit faster, but when the algorithm involves modifying the thing we're iterating over, I prefer the explicit index.
I prefer not to touch the original list and do as #Martol1ni, but one way to do it in place and not be affected by the removal of elements would be to iterate backwards:
for i in reversed(range(len()):
# do the filtering...
That will affect only the indices of elements that you have tested/removed already
Try the filter command, and you can override the original list with it too if you don't need it.
def cmp(i): #Comparator function returning a boolean for a given item
...
# mylist is the initial list
mylist = filter(cmp, mylist)
mylist is now a generator of suitable items. You can use list(mylist) if you need to use it more than once.
Haven't tried this yet but.. i'll give it a quick shot:
new_list = [old.pop(i) for i, x in reversed(list(enumerate(old))) if comparator(x)]
You can do this, might be one line too much though.
new_list1 = [x for x in old_list if your_comparator(x)]
new_list2 = [x for x in old_list if x not in new_list1]

How to use pop for multidimensional array in pythonic way

I want to remove the list items found in list B from the list A. This is the function I wrote:
def remove(A,B):
to_remove=[];
for i in range(len(A)):
for j in range(len(B)):
if (B[j]==A[i]):
to_remove.append(i);
for j in range(len(to_remove)):
A.pop(to_remove[j]);
Is this the normal way to do it ? Although, this works completely fine (if typos, I don't know), I think there might be more pythonic way to do it. Please suggest.
Convert B to a set first and then create a new array from A using a list comprehension:
s = set(B)
A = [item for item in A if item not in s]
Item lookup in a set is an O(1) operation.
If you don't want to change the id() of A, then:
A[:] = [item for item in A if item not in s]
First, note that your function doesn't work right. Try this:
A = [1, 2, 3]
B = [1, 2, 3]
remove(A, B)
You'll get an IndexError, because the correct indices to delete change each time you do a .pop().
You'll doubtless get answers recommending using sets, and that's indeed much better if the array elements are hashable and comparable, but in general you may need something like this:
def remove(A, B):
A[:] = [avalue for avalue in A if avalue not in B]
That works for any kinds of array elements (provided only they can be compared for equality), and preserves the original ordering. But it takes worst-case time proportional to len(A) * len(B).
List comprehenstion to the rescue:
[item for item in A if item not in B]
This however creates a new list. You can return the list from the function.
Or, if you are ok with loosing any duplicates in list A, or there are no duplicates, you can use set difference:
return list(set(A) - set(B))
One caveat is, this won't preserve the order of elements in A. So, if you want elements in order, this is not what you want. Use the 1st approach instead.
What about list comprehension?
def remove(removeList, fromList):
return [x for x in fromList if x not in removeList]
Also, to make life easier and removing faster you can make a set from list removeList, leaving only unique elements:
def remove(removeList, fromList):
removeSet = set(removeList)
return [x for x in fromList if x not in removeSet]
>>> print remove([1,2,3], [1,2,3,4,5,6,7])
[4, 5, 6, 7]
And, of course, you can use built-in filter function, though someone will say that it's non-pythonic, and you should use list generators instead. Either way, here is an example:
def remove(removeList, fromList):
removeSet = set(removeList)
return filter(lambda x : x not in removeSet, fromList)

Categories