Is there a str.join() for lists? - python

I understand str.join():
>>> '|'.join(['1','2','3'])
'1|2|3'
Is there something which outputs a list? Is there a function that will output:
['1', '|', '2','|', '3']
That is, a str.join() for lists? (or any other iterable?)

list('|'.join(['1','2','3']))
should do the trick where you are working with a list of chars.
A more generic solution, that works for all objects is:
from itertools import izip_longest, chain
def intersperse(myiter, value):
return list(
chain.from_iterable(izip_longest(myiter, [], fillvalue=value))
)[:-1]
I'm not aware of a built-in/std-library version of this function.
In action:
print intersperse([1,2,3], '|')
outputs:
[1, '|', 2, '|', 3]

How about this?
>>> list('|'.join(['1','2','3']))
['1', '|', '2', '|', '3']

a = [1, 2, 'str', 'foo']
print [x for y in a for x in y, '|'][:-1]
# [1, '|', 2, '|', 'str', '|', 'foo']
For the general case, consider the roundrobin itertools recipe

This simple generator avoids building a list (faster, saves memory):
def intersperse(iterable, element):
iterable = iter(iterable)
yield next(iterable)
while True:
next_from_iterable = next(iterable)
yield element
yield next_from_iterable
Example:
>>> list(intersperse(['1', '2', '3'], '|'))
['1', '|', '2', '|', '3']

Related

using python 3.6 to slice substring with same char [duplicate]

I am not well experienced with Regex but I have been reading a lot about it. Assume there's a string s = '111234' I want a list with the string split into L = ['111', '2', '3', '4']. My approach was to make a group checking if it's a digit or not and then check for a repetition of the group. Something like this
L = re.findall('\d[\1+]', s)
I think that \d[\1+] will basically check for either "digit" or "digit +" the same repetitions. I think this might do what I want.
Use re.finditer():
>>> s='111234'
>>> [m.group(0) for m in re.finditer(r"(\d)\1*", s)]
['111', '2', '3', '4']
If you want to group all the repeated characters, then you can also use itertools.groupby, like this
from itertools import groupby
print ["".join(grp) for num, grp in groupby('111234')]
# ['111', '2', '3', '4']
If you want to make sure that you want only digits, then
print ["".join(grp) for num, grp in groupby('111aaa234') if num.isdigit()]
# ['111', '2', '3', '4']
Try this one:
s = '111234'
l = re.findall(r'((.)\2*)', s)
## it this stage i have [('111', '1'), ('2', '2'), ('3', '3'), ('4', '4')] in l
## now I am keeping only the first value from the tuple of each list
lst = [x[0] for x in l]
print lst
output:
['111', '2', '3', '4']
If you don't want to use any libraries then here's the code:
s = "AACBCAAB"
L = []
temp = s[0]
for i in range(1,len(s)):
if s[i] == s[i-1]:
temp += s[i]
else:
L.append(temp)
temp = s[i]
if i == len(s)-1:
L.append(temp)
print(L)
Output:
['AA', 'C', 'B', 'C', 'AA', 'B']

Remove duplicates from a nested list

I have a list
A = [['1'],['1','2'],['1','2','3','1','2'],['3','3','3']]
and I want to make my list to
A = [['1'],['1','2'],['1','2','3'],['3']]
ie I want to remove duplicate elements within the elements in a list ..
One-liner (If order doesn't matter) :
A = [['1'],['1','2'],['1','2','3','1','2'],['3','3','3']]
A = [list(set(a)) for a in A]
print(A) # => [['1'], ['2', '1'], ['3', '2', '1'], ['3']]
One-liner (If order matters) :
A = [['1'],['1','2'],['1','2','3','1','2'],['3','3','3']]
A = [sorted(set(a), key=a.index) for a in A]
print(A) # => [['1'], ['1', '2'], ['1', '2', '3'], ['3']]
A functional version, with functools:
>>> import functools
>>> A = [['1'],['1','2'],['1','2','3','1','2'],['3','3','3']]
>>> print ([functools.reduce(lambda result,x:result if x in result else result+[x], xs, []) for xs in A])
[['1'], ['1', '2'], ['1', '2', '3'], ['3']]
The lambda function adds an element to the result list only if that element is not present in the list. Not very efficient, but keeps the order of elements.
Also note that with Python 2, you don't need to import functools: reduce is a builtin function.
You can use a generator:
def remove_dups(l):
for a in l:
new_l = []
for b in a:
if b not in new_l:
new_l.append(b)
yield new_l
A = [['1'],['1','2'],['1','2','3','1','2'],['3','3','3']]
print(list(remove_dups(A)))
Output:
[['1'], ['1', '2'], ['1', '2', '3'], ['3']]

Changing lists inside a list to strings inside a list

How do I return my list so that the list is composed of strings rather than lists?
Here is my attempt:
def recipe(listofingredients):
listofingredients = listofingredients
newlist = []
newlist2 = []
for i in listofingredients:
listofingredients = i.strip("\n")
newlist.append(listofingredients)
for i in newlist:
newlist = i.split()
newlist2.append(newlist)
return newlist2
result = recipe(['12345\n','eggs 4\n','$0.50\n','flour 5\n','$2.00\n'])
print result
And my output is this:
[['12345'], ['eggs', '4'], ['$0.50'], ['flour', '5'], ['$2.00']]
Desired output:
['12345', 'eggs', '4', '$0.50', 'flour', '5', '$2.00']
I know that my issue here is appending one list to another, but I'm not sure how to use .strip() and .split() on anything other than a list.
Use extend and split:
>>> L = ['12345\n','eggs 4\n','$0.50\n','flour 5\n','$2.00\n']
>>> res = []
>>> for entry in L:
res.extend(entry.split())
>>> res
['12345', 'eggs', '4', '$0.50', 'flour', '5', '$2.00']
split splits at white spaces per default. Strings with a new line a the end and no space inside are turned into a one-element list:
>>>'12345\n'.split()
['12345']
Strings with a space inside split into a two-element list:
>>> 'eggs 4\n'.split()
['eggs', '4']
The method extend() helps to build a list from other lists:
>>> L = []
>>> L.extend([1, 2, 3])
>>> L
[1, 2, 3]
>>> L.extend([4, 5, 6])
L
[1, 2, 3, 4, 5, 6]
You can use Python's way of doing this. Take the advantage of list comprehension and strip() method.
recipes = ['12345\n','eggs 4\n','$0.50\n','flour 5\n','$2.00\n']
recipes = [recipe.split() for recipe in recipes]
print sum(recipes, [])
Now the result will be
['12345', 'eggs', '4', '$0.50', 'flour', '5', '$2.00']
For further reading
https://stackoverflow.com/a/716482/968442
https://stackoverflow.com/a/716489/968442

How can i sort the list with keys in python

I have the two list dictionary like this
obj1 = [mydict['obj1'],mydict['obj2'],mydict['obj3'],mydict['obj4']]
obj2 = [mydict['obj1'],mydict['obj2'],mydict['obj3'],mydict['obj4'], mydict['obj5'] ]
Now i want that
Count the number of elements in each list
Then based on whichever is greater then get that list of objects
I want a single list which conatins the above two list of(list of) dictionaries based on the higher number of elements so that i cause something like this
mylist = myfunc(objects1, objects2 )
mylist should be a list like [objects1, objects2] depending upon who has greater number of objects.
what is the best way to do that with less lines of code
Something like EDIT
mylist = sorted([obj1, obj2], key=lambda a: len(a), reverse=True)
There's no need to use a lambda function if it's just going to call a function anyway.
>>> objects1 = [1, 2, 3]
>>> objects2 = ['1', '2', '3', '4']
>>>
>>> mylist = [objects1, objects2]
>>> max(mylist, key=len)
['1', '2', '3', '4']
>>> sorted(mylist, key=len, reverse=True)
[['1', '2', '3', '4'], [1, 2, 3]]
objects1 = [1, 2, 3]
objects2 = ['1', '2', '3', '4']
mylist = [objects1, objects2]
mylist.sort(key=len, reverse=True)
print mylist
[['1', '2', '3', '4'], [1, 2, 3]]

How can I find the locations of an item in a Python list of lists?

I want to find the location(s) of a specific item in a list of lists. It should return a list of tuples, where each tuple represents the indexes for a specific instance of the item. For example:
list = [['1', '2', '4', '6'], ['7', '0', '1', '4']]
getPosition('1') #returns [(0, 0), (1, 2)]
and getPosition('7') #returns [(1,0)]
If you want something that will both
find duplicates and
handle nested lists (lists of lists of lists of ...)
you can do something like the following:
def get_positions(xs, item):
if isinstance(xs, list):
for i, it in enumerate(xs):
for pos in get_positions(it, item):
yield (i,) + pos
elif xs == item:
yield ()
Testing this:
>>> xs = [['1', '2', '4', '6'],
... ['7', '0', '1', '4'],
... [ [ '0', '1', '1'], ['1']]
... ]
>>> print list(get_positions(xs, '1'))
[(0, 0), (1, 2), (2, 0, 1), (2, 0, 2), (2, 1, 0)]
It looks likes you want, for a list of sublists and a given item, to return a list of pairs where each pair is (the index of the sublist, the index of the item within the sublist). You can do that using list comprehensions and Python's built in enumerate() function:
def getPosition(list, item):
return [(i, sublist.index(item)) for i, sublist in enumerate(list)]
Edit: See #scribble's answer above/below.
def getPosition(list, item):
return [(i, sublist.index(item)) for i, sublist in enumerate(list)
if item in sublist]
def get_positions(xs, target):
return [(i,e.index(target)) for i,e in enumerate(xs)]
That's a good starting point. Presumably you have some sort of class such as
class SomeClass:
def __init__(self):
self.xs = [['1','2','4','6'], ['7','0','1','4']]
def get_positions(self, target):
return [(i,e.index(target)) for i,e in enumerate(self.xs)]
which in this case would let you say
model = SomeClass()
model.get_position(1) # returns [(0,0), (1,2)]
Note that in both cases you'll get an exception if your target isn't in every one of your sublists. The question does not specify whether this is the desired behavior.
If you don't want a exception if the item is not in the list try this. Also as a generator because they are cool and versatile.
xs = [['1', '2', '4', '6'], ['7', '0', '1', '4']]
def get_positions(xs, item):
for i, xt in enumerate( xs ):
try: # trying beats checking
yield (i, xt.index(item))
except ValueError:
pass
print list(get_positions(xs, '1'))
print list(get_positions(xs, '6'))
# Edit for fun: The one-line version, without try:
get_positions2 = lambda xs,item: ((i,xt.index(item)) for i, xt in enumerate(xs) if item in xt)
print list(get_positions2(xs, '1'))
print list(get_positions2(xs, '6'))
A while ago I wrote a library for python to do list matching that would fit the bill pretty well. It used the tokens ?, +, and * as wildcards, where ? signifies a single atom, + is a non-greedy one-or-more, and * is greedy one-or-more. For example:
from matching import match
match(['?', 2, 3, '*'], [1, 2, 3, 4, 5])
=> [1, [4, 5]]
match([1, 2, 3], [1, 2, 4])
=> MatchError: broken at 4
match([1, [2, 3, '*']], [1, [2, 3, 4]])
=> [[4]]
match([1, [2, 3, '*']], [1, [2, 3, 4]], True)
=> [1, 2, 3, [4]]
Download it here: http://www.artfulcode.net/wp-content/uploads/2008/12/matching.zip
Here is a version without try..except, returning an iterator and that for
[['1', '1', '1', '1'], ['7', '0', '4']]
returns
[(0, 0), (0, 1), (0, 2), (0, 3)]
def getPosition1(l, val):
for row_nb, r in enumerate(l):
for col_nb in (x for x in xrange(len(r)) if r[x] == val):
yield row_nb, col_nb
The most strainghtforward and probably the slowest way to do it would be:
>>> value = '1'
>>> l = [['1', '2', '3', '4'], ['3', '4', '5', '1']]
>>> m = []
>>> for i in range(len(l)):
... for j in range(len(l[i])):
... if l[i][j] == value:
... m.append((i,j))
...
>>> m
[(0, 0), (1, 3)]
Here is another straight forward method that doesn't use generators.
def getPosition(lists,item):
positions = []
for i,li in enumerate(lists):
j = -1
try:
while True:
j = li.index(item,j+1)
positions.append((i,j))
except ValueError:
pass
return positions
l = [['1', '2', '4', '6'], ['7', '0', '1', '4']]
getPosition(l,'1') #returns [(0, 0), (1, 2)]
getPosition(l,'9') # returns []
l = [['1', '1', '1', '1'], ['7', '0', '1', '4']]
getPosition(l,'1') #returns [(0, 0), (0, 1), (0,2), (0,3), (1,2)]

Categories

Resources