Create new lists with del function - python

I have a list
a = ['a', 'b', 'c']
And I want to create a function Delete where it would print to a new list the lists['a', 'b'], ['b', 'c'] and ['a', 'c'].
My main goal here is designing a function that would return a set of lists consisting of the main list without an element of it.

What you want is all combinations of length n-1 where n is the length of your list.
>>> from itertools import combinations
>>> a = ['a', 'b', 'c']
>>> map(list, combinations(a, len(a)-1))
[['a', 'b'], ['a', 'c'], ['b', 'c']]
This will give you a list of lists.
Note that a set of lists which you requested is not possible because lists are not hashable.

Related

Python indirect list indexing [duplicate]

In Python I have a list of elements aList and a list of indices myIndices. Is there any way I can retrieve all at once those items in aList having as indices the values in myIndices?
Example:
>>> aList = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> myIndices = [0, 3, 4]
>>> aList.A_FUNCTION(myIndices)
['a', 'd', 'e']
I don't know any method to do it. But you could use a list comprehension:
>>> [aList[i] for i in myIndices]
Definitely use a list comprehension but here is a function that does it (there are no methods of list that do this). This is however bad use of itemgetter but just for the sake of knowledge I have posted this.
>>> from operator import itemgetter
>>> a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> my_indices = [0, 3, 4]
>>> itemgetter(*my_indices)(a_list)
('a', 'd', 'e')
Indexing by lists can be done in numpy. Convert your base list to a numpy array and then apply another list as an index:
>>> from numpy import array
>>> array(aList)[myIndices]
array(['a', 'd', 'e'],
dtype='|S1')
If you need, convert back to a list at the end:
>>> from numpy import array
>>> a = array(aList)[myIndices]
>>> list(a)
['a', 'd', 'e']
In some cases this solution can be more convenient than list comprehension.
You could use map
map(aList.__getitem__, myIndices)
or operator.itemgetter
f = operator.itemgetter(*aList)
f(myIndices)
If you do not require a list with simultaneous access to all elements, but just wish to use all the items in the sub-list iteratively (or pass them to something that will), its more efficient to use a generator expression rather than list comprehension:
(aList[i] for i in myIndices)
Alternatively, you could go with functional approach using map and a lambda function.
>>> list(map(lambda i: aList[i], myIndices))
['a', 'd', 'e']
I wasn't happy with these solutions, so I created a Flexlist class that simply extends the list class, and allows for flexible indexing by integer, slice or index-list:
class Flexlist(list):
def __getitem__(self, keys):
if isinstance(keys, (int, slice)): return list.__getitem__(self, keys)
return [self[k] for k in keys]
Then, for your example, you could use it with:
aList = Flexlist(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
myIndices = [0, 3, 4]
vals = aList[myIndices]
print(vals) # ['a', 'd', 'e']

Python: How to generate list with items repeating in two lists

I have two lists of items:
list_1 = ['A', 'B', 'C', 'C', 'D']
list_2 = ['C', 'C', 'F', 'A', 'G', 'D', 'C']
I want to create a new list with the elements that are in the two lists. Like this:
['A', 'C', 'C', 'D']
Notice that it should take in mind that any item can repeat in list several times and should be in the new list as many times as it is repeated in both lists. For instance, 'C' is repeated 2 times in list_1 and 3 times in list_2 so it appears 2 times in the result.
The classic method to do it will be:
import copy
result = []
list_2 = fruit_list_2.copy()
for fruit in fruit_list_1:
if fruit in list_2:
result.append(fruit)
list_2.remove(fruit)
but I am interested to do it by generation lists: [number for number in numbers if number > 0]. Is it possible?
If you aren't terribly concerned about the ordering of the new list, you can use collections.Counter.
>>> list((Counter(list_1) & Counter(list_2)).elements())
['A', 'C', 'C', 'D']
& takes the intersection of the two as multi-sets, with the minimum count used for common elements. The elements method returns the items in the result as an iterator, hence the list wrapper`.
read about collections.Counter
from collections import Counter
list_3 = list((Counter(list_1) & Counter(list_2)).elements())
I think it's as simple as:
list_1 = ['A', 'B', 'C', 'C', 'D']
list_2 = ['C', 'C', 'F', 'A', 'G', 'D', 'C']
list_3 = [x for x in list_1 if x in list_2]
print(list_3)
# returns ['A', 'C', 'C', 'D']
Try this:
[common for common in list_1 if common in list_2]
Happy learning...:)

Python permutations of heterogenous list elements

This is the sequence:
l = [['A', 'G'], 'A', ['A', 'C']]
I need the three element sequence back for each permutation
all = ['AAA','GAA','AAC','GAC']
I can't figure this one out! I'm having trouble retaining the permutation order!
You want the product:
from itertools import product
l = [['A', 'G'], 'A', ['A', 'C']]
print(["".join(p) for p in product(*l)])

Create all sequences from the first item within a list

Say I have a list, ['a', 'b', 'c', 'd']. Are there any built-ins or methods in Python to easily create all contiguous sublists (i.e. sub-sequences) starting from the first item?:
['a']
['a', 'b']
['a', 'b', 'c']
['a', 'b', 'c', 'd']
in Python?
Note that I am excluding lists/sequences such as ['a' ,'c'], ['a', 'd'], ['b'], ['c'] or ['d']
To match your example output (prefixes), then you can just use:
prefixes = [your_list[:end] for end in xrange(1, len(your_list) + 1)]
You can do this with a simple list comprehension:
>>> l = ['a', 'b', 'c', 'd']
>>>
>>> [l[:i+1] for i in range(len(l))]
[['a'], ['a', 'b'], ['a', 'b', 'c'], ['a', 'b', 'c', 'd']]
See also: range()
If you're using Python 2.x, use xrange() instead.
A little more Pythonic than using (x)range (with the benefit of being the same solution for either Python 2 or Python 3):
lst = list('abcde')
prefixes = [ lst[:i+1] for i,_ in enumerate(lst) ]
If you decided that the empty list should be a valid (zero-length) prefix, a small hack will include it:
# Include 0 as an slice index and still get the full list as a prefix
prefixes = [ lst[:i] for i,_ in enumerate(lst + [None]) ]
Just as an alternative:
def prefixes(seq):
result = []
for item in seq:
result.append(item)
yield result[:]
for x in prefixes(['a', 'b', 'c', 'd']):
print(x)

How to maintain consistency in list?

I have a list like
lst = ['a', 'b', 'c', 'd', 'e', 'f']
I have a pop position list
p_list = [0,3]
[lst.pop(i) for i in p_list] changed the list to ['b', 'c', 'd', 'f'], here after 1st iteration list get modified. Next pop worked on the new modified list.
But I want to pop the element from original list at index [0,3] so, my new list should be
['b', 'c', 'e', 'f']
Lots of reasonable answers, here's another perfectly terrible one:
[item for index, item in enumerate(lst) if index not in plist]
You could pop the elements in order from largest index to smallest, like so:
lst = ['a', 'b', 'c', 'd', 'e', 'f']
p_list = [0,3]
p_list.sort()
p_list.reverse()
[lst.pop(i) for i in p_list]
lst
#output: ['b', 'c', 'e', 'f']
Do the pops in reversed order:
>>> lst = ['a', 'b', 'c', 'd', 'e', 'f']
>>> p_list = [0, 3]
>>> [lst.pop(i) for i in reversed(p_list)][::-1]
['a', 'd']
>>> lst
['b', 'c', 'e', 'f']
The important part here is that inside of the list comprehension you should always call lst.pop() on later indices first, so this will only work if p_list is guaranteed to be in ascending order. If that is not the case, use the following instead:
[lst.pop(i) for i in sorted(p_list, reverse=True)]
Note that this method makes it more complicated to get the popped items in the correct order from p_list, if that is important.
Your method of modifying the list may be error prone, why not use numpy to only access the index elements that you want? That way everything stays in place (in case you need it later) and it's a snap to make a new pop list. Starting from your def. of lst and p_list:
from numpy import *
lst = array(lst)
idx = ones(lst.shape,dtype=bool)
idx[p_list] = False
print lst[idx]
Gives ['b' 'c' 'e' 'f'] as expected.

Categories

Resources