Creating list of lists and skipping elements in Python - list

How can I create a list of list using [x for x in input] (where input is a list of strings) and skip elements if they satisfy certain condition? For example, this is the list of lists:
[['abc', 'def', 'ghi'], ['abc', 'd_f', '+hi'], ['_bc', 'def', 'ghi']]
and this should be the output -- with skipped elements containing either '_' or '+':
[['abc', 'def', 'ghi'], ['abc'], ['def', 'ghi']]
Thanks!

You'll need a sub-list comprehension:
[[item for item in sub if not any(char in item for char in '_+')] for sub in input]
which is a simplified version of:
result = []
for sub in input:
result.append([])
for item in sub:
should_add = True
for char in '_+':
if char in item:
should_add = False
break
if should_add:
result[-1].append(item)

Pretty similar to the other answer except tests if the string contains only alpha numeric characters as opposed to specifically '_' and '+'. Loops through each sub list then the strings in each sub list.
filtered = [[s for s in l if s.isalpha()] for l in lists]
print(filtered)
[['abc', 'def', 'ghi'], ['abc'], ['def', 'ghi']]

Another short version using a set:
stuff= [['abc', 'def', 'ghi'], ['abc', 'd_f', '+hi'], ['_bc', 'def', 'ghi']]
unwanted = {'+', '-'}
filtered = [[item for item in s if not set(s) & unwanted] for s in stuff]

Related

Prolog - Add a special character to every element of a list

I'm trying to add a special character (*) to every element of a list.
I want to add it in the beginning and the end of the element, so if I have:
list(apple,orange,pear)
It would be:
list(*apple*,*orange*,*pear*)
Is there a way to do that in prolog?
Thank you.
To concatenate two atoms, you can use the ISO predicate atom_concat/3:
?- atom_concat('*', apple, StarAtom), atom_concat(StarAtom, '*', StarAtomStar).
StarAtom = '*apple',
StarAtomStar = '*apple*'.
Using this predicate, you can define the following new predicate:
% starry_atom(+Atom, -StarAtomStar)
starry_atom(Atom, StarAtomStar) :-
atom_concat('*', Atom, StarAtom),
atom_concat(StarAtom, '*', StarAtomStar).
Example:
?- starry_atom(apple, StarryAtom).
StarryAtom = '*apple*'.
To apply starry_atom/2 to all elements of a list, supposing that all elements of the list are atoms, you can use the predicate maplist/3.
?- maplist(starry_atom, [apple, orange, pear], List).
List = ['*apple*', '*orange*', '*pear*'].
NOTE In SWI-Prolog, you can also use the predicate atomic_list_concat/2.
?- atomic_list_concat(['*', apple, '*'], Atom).
Atom = '*apple*'.

python split list of strings, where index out of range

How do I return the second alpha character [if there is a second alpha character] of each item in a list? If there is not a second alpha character do nothing.
list = ["a b", "c d", "e"]
for item in list:
x = item.split()[1]
The last loop returns "IndexError: list index out of range" due to the fact that there is not a second item.
The error occurs because there's the item "e" which is split into one chunk (indexed with 0)Also, don't give variable reserved name as list.
For your simple case you may use the following:
l = ["a b", "c d", "e"]
result = [i.split()[1] if ' ' in i else i for i in l]
print(result)
The output:
['b', 'd', 'e']
This takes the item even if the length of it is 1(that is, it cannot be split)
x = [] #creates a list to hold the values
for item in list:
if(len(item)) == 1:
x.append(item)
else:
x.append(item.split()[1])
print(x)
This, ignores the item if it is not splittable:
x = [] #creates a list to hold the values.
for item in list:
if len(item) > 1:
x.append(item.split()[1])
print(x)

Sorting 3 lists in python into 1 formatted list

I have a set of lists:
A = [[A1,A2,A3],[A4,A5,A6]...,[A(n-2),A(n-1),A(n)]] #A has length n
B = [[B1,B2,B3],[B4,B5,B6]...,[B(n-2),B(n-1),B(n)]] #B has length n
C = [[C1,C2,C3],[C4,C5,C6]...,[C(n-2),C(n-1),C(n)]] #C has length n
and I want to sort it into the following format:
f = [(A1,A2,A3,B1,B2,B3,C1,C2,C3),(A4,A5,A6,B4,B5,B6,C4,C5,C6),...,(A(n-2),A(n-1),A(n),B(n-2),B(n-1),B(n),C(n-2),C(n-1),C(n))]
I'm pretty new to python and I cant think of a way to do this.
Any input will be greatly appreciated.
Ive started by using:
for item in range(len(A)):
f[item][0] = A[item][0]
f[item][1] = A[item][1]
f[item][2] = A[item][2]
for item in range(len(B)):
f[item][3] = B[item][0]
f[item][4] = B[item][1]
f[item][5] = B[item][2]
for item in range(len(C)):
f[item][6] = C[item][0]
f[item][7] = C[item][1]
f[item][8] = C[item][2]
But this just sets all items in the list f to be equal to the last item in f for some reason.
interleave sublists using zip, and flatten the resulting sublists with itertools.chain in a list comprehension with this nice one-liner:
import itertools
A = [["A1","A2","A3"],["A4","A5","A6"]] #A has length n
B = [["B1","B2","B3"],["B4","B5","B6"]] #B has length n
C = [["C1","C2","C3"],["C4","C5","C6"]] #C has length n
print([tuple(itertools.chain(*l)) for l in zip(A,B,C)])
result:
[('A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3'), ('A4', 'A5', 'A6', 'B4', 'B5', 'B6', 'C4', 'C5', 'C6')]
General case if you have a variable amount of lists, stored in a list of lists:
list_of_lists = [A,B,C]
print([tuple(itertools.chain(*l)) for l in zip(*list_of_lists)])
(use * operator to expand list items to arguments for zip)
note: works well if sublists have different lengths, as long as there are as many sublists in each list (else zip will drop the last one(s)):
A = [["A1","A2","A3"],["A4","A5","A6","A7"],["I will be discarded"]] #A has length n+1, last element will be lost
B = [["B1","B2","B3","B3bis"],["B4","B5","B6"]] #B has length n
C = [["C0","C1","C2","C3"],["C4","C5","C6"]] #C has length n
yields:
[('A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'B3bis', 'C0', 'C1', 'C2', 'C3'), ('A4', 'A5', 'A6', 'A7', 'B4', 'B5', 'B6', 'C4', 'C5', 'C6')]

Find unique items in a list using a passed value for range of the list (sublists)

I am trying to tie two different things together.
1. Find and print unique items in a list.
2. Pass a int value and print unique items in the first n items
I have two things that work, but not in conjunction, to split the list into sub-lists of n:
def find_uniques(3):
lista = ['a', 'a', 'b','c','d','c','e','d','e','f','f']
lists = [lista[x:x+n] for x in xrange(0, len(lista), n)]
print lists
[['a', 'a', 'b'], ['c', 'd', 'c'], ['e', 'd', 'e'], ['f', 'f']]
# 2nd part works on the whole list
print [a for a in lista if lista.count(a) == 1]
['b']
# How do I get the second part to work on the sub lists, and give me back unique chars from each sub list.
The output I am looking for:
[['b'],['d'], ['d']]
Usually it is easier to just split out these operations instead of merging, but here is a nested list comprehension.
lista = ['a', 'a', 'b','c','d','c','e','d','e','f','f']
n = 3
[[ item for item in sublist if sublist.count(item) == 1] for sublist in [ lista[x:x+n] for x in xrange(0, len(lista), n) ] ]
Personally, although it is longer, I prefer a more readable version like so:
def findunique(lista,n=3):
listoflists = [ lista[x:x+n] for x in xrange(0,len(lista),n) ]
results = []
for sublist in listoflists:
unique = [ item for item in sublist if sublist.count(item) == 1]
if unique:
results.append(unique)
return results
lista = ['a','a','b','c','d','c','e','d','e','f','f']
print findunique(lista,3)

Python: re.sub single item in list with multiple items

I'm new to Python and trying to use re.sub or other approach to find individual items in a list and replace with multiple items. For example:
import re
list = ['abc', 'def']
tolist = []
for item in list:
a = re.sub(r'^(.)(.)(.)$', '\\1\\2', '\\2\\3', item)
tolist.append(a)
print tolist # want: ['ab', 'bc', 'de', 'ef']
The '\1\2', '\2\3' part clearly doesn't work, just there to lamely illustrate the idea.
You could pair characters without regexes:
lst = ['abc', 'def']
result = [a+b for chars in lst for a, b in zip(chars, chars[1:])]
print(result)
# -> ['ab', 'bc', 'de', 'ef']
Here's a rather generic approach where you have a list of tuples for all the substitutions you want to do with each item:
In [1]: import re
In [2]: subs = [(r'^(.)(.)(.)$', r'\1\2'), (r'^(.)(.)(.)$', r'\2\3')]
In [3]: inlist = ['abc', 'def']
In [4]: [re.sub(*sub, string=s) for s in inlist for sub in subs]
Out[4]: ['ab', 'bc', 'de', 'ef']
The second element in each tuple can also be a function, because re.sub allows it. I renamed your initial list because list is a built-in type name and shouldn't be used for variables.
>>> res = []
>>> m = re.compile('(..)')
>>> for items in list:
... for p in range(0,len(items)):
... r = m.search(items[p:])
... if r != None:
... res.append(r.group())
make a regexp that matches two characters and groups them
first for loop, iterate the list
second for loop, character indexes in each list item
search for the character pairs starting at further on offsets
store anything that's found