Transforming a string in a list - python

How can I transforms strings in list return a list consisting the elements of strings and the lengths of strings?
Just like add_sizes([str]) -> [(str, int)]
Here is what I did:
def add_sizes(strings):
for i in strings:
return [(i, (len(i)))]
but this only works for one string, What should I do if I have more than one string?

Use list_comprehension
>>> l = ['foo', 'bar', 'j', 'mn']
>>> [(i,len(i)) for i in l]
[('foo', 3), ('bar', 3), ('j', 1), ('mn', 2)]
Defining it as a seperate function.
def add_sizes(l):
return [(i,len(i)) for i in l]

Your mistake
You are returning after you check the first element, hence you will get only the value of the first string. A work around can be
def add_sizes(strings):
temp = []
for i in strings:
temp.append((i, (len(i))))
return temp
Better ways to do it
A better way using map
>>> l = ['abc','defg','hijkl']
>>> map(lambda x:(x,len(x)),l)
[('abc', 3), ('defg', 4), ('hijkl', 5)]
And you can define your function as
def add_sizes(l):
return map(lambda x:(x,len(x)),l)
Or using a list comp as shown in Avinash's answer

I would use map and zip:
def add_sizes(strings):
return list(zip(strings, map(len, strings)))
print(add_sizes(["foo","bar","foobar"]))
[('foo', 3), ('bar', 3), ('foobar', 6)]
If you will have a mixture of lists and single strings you need to catch that:
def add_sizes(strings):
return zip(strings, map(len, strings)) if not isinstance(strings, str) else [(strings, len(strings))]

Use List Comprehension:
def add_sizes(slist):
out = [(s, len(s)) for s in slist]
return out

Yes correct, because return statement is inside for loop,so during first iteration it will return.
Move return statement outside of for loop and create new list to add(append) every element and its length as tuple.
Demo:
>>> def add_sizes(input_list):
... result = []
... for i in input_list:
... result.append((i, len(i)), )
... return result
...
>>> l1 = ["asb", "werg", "a"]
>>> add_sizes(l1)
[('asb', 3), ('werg', 4), ('a', 1)]
>>>

Related

Convert list into tuple then add this tuple into list in python

Hi I want my output to be
add_sizes(['hello', 'world']) -> [('hello', 5), ('world', 5)]
but I'm getting
add_sizes(['hello', 'world']) -> [('hello', 5), ('hello', 5, 'helloworld', 5)]
My code is
def add_sizes(strings):
s = ()
t=[]
m=[]
for i in strings:
x=i
for i,c in enumerate(list(x)):
t.append(c)
l=(str(''.join(t)),i+1)
s += l
m.append(s)
print(m)
Any suggestion would be appreciated thanks
Just use a list comprehension:
>>> def add_sizes(strings):
... return [(s, len(s)) for s in strings]
...
>>>
>>> add_sizes(['hello', 'world'])
[('hello', 5), ('world', 5)]
Or if you want to do it in-place:
>>> def add_size(strings):
... for i, s in enumerate(strings):
... strings[i] = (s, len(s))
... return strings
...
>>> add_sizes(['hello', 'world'])
[('hello', 5), ('world', 5)]
Someone already gave a complete solution so I'll just post mine too:
def add_sizes(strings):
l = []
for string in strings:
l.append((string, len(string)))
return l
def add_sizes(strings):
return [(s, len(s)) for s in strings]

returnig elements in a list with their positions in that list

I have a list, and i want to return each element in that list along with its position in it.
for example:
my_enumerate(['dog', 'pig', 'cow'])
should return:
[(0, 'dog'), (1, 'pig'), (2, 'cow')]
The following is how I've approached it:
def my_enumerate(items):
''' returning position of item in a list'''
lista = []
for num in range(0, len(items)+1):
for item in items:
lista.append("({0}, {1})".format(num, item))
return lista
which returned to me:
['(0, dog)', '(0, pig)', '(0, cow)', '(1, dog)', '(1, pig)', '(1, cow)', '(2, dog)', '(2, pig)', '(2, cow)', '(3, dog)', '(3, pig)', '(3, cow)']
The function should behave exactly like the built-in enumerate function, but I'm not allowed to use it.
Your program produces cartesian product of all the indexes and elements of the list. It takes each index and produces all the strings with the elements in the list. Also, note that, you should iterate only till the length of the list, when you do len(items) + 1, you are actually exceeding the actual length of the list.
You can use only the first loop, like this
>>> def my_enumerate(items):
... lista = []
... for num in range(len(items)):
... lista.append("({0}, {1})".format(num, items[num]))
... return lista
...
>>> my_enumerate(['dog', 'pig', 'cow'])
['(0, dog)', '(1, pig)', '(2, cow)']
You can also use a simple list comprehension, like this
>>> def my_enumerate(items):
... return ["({0}, {1})".format(num, items[num]) for num in range(len(items))]
...
>>> my_enumerate(['dog', 'pig', 'cow'])
['(0, dog)', '(1, pig)', '(2, cow)']
Note 1: In Python 3.x, you don't have to use the positions in the format string unless it is necessary. So, "({}, {})".format is enough.
Note 2: If you actually wanted to return tuples, like enumerate, then you should not use string formatting, instead prepare tuples like this
>>> def my_enumerate(items):
... return [(num, items[num]) for num in range(len(items))]
...
>>> my_enumerate(['dog', 'pig', 'cow'])
[(0, 'dog'), (1, 'pig'), (2, 'cow')]
Note 3: If you actually wanted to simulate enumerate like it works in Python 3.x, then you should better use a generator function, like this
>>> def my_enumerate(items):
... for num in range(len(items)):
... yield (num, items[num])
...
...
>>> my_enumerate(['dog', 'pig', 'cow'])
<generator object my_enumerate at 0x7f5ff7abf900>
>>> list(my_enumerate(['dog', 'pig', 'cow']))
[(0, 'dog'), (1, 'pig'), (2, 'cow')]
Note 4: More good news is, you can write the same my_enumerate, with yield from and a generator expression, like this
>>> def my_enumerate(items):
... yield from ((num, items[num]) for num in range(len(items)))
...
>>> my_enumerate(['dog', 'pig', 'cow'])
<generator object my_enumerate at 0x7f5ff7abfe10>
>>> list(my_enumerate(['dog', 'pig', 'cow']))
[(0, 'dog'), (1, 'pig'), (2, 'cow')]
If you write it as a generator, it will even work with infinite generators:
def my_enumerate(items):
i = 0
for e in items:
yield (i, e)
i += 1
print(list(my_enumerate(['dog', 'pig', 'cow']))
You can do it in a one-liner pretty easily using zip, range, and len:
def my_enumerate(items):
return zip(range(len(myList)), myList)
my_list = ['dog', 'pig', 'cow']
print(my_enumerate(my_list)) # prints [(0, 'dog'), (1, 'pig'), (2, 'cow')]
The above would be the Python 2 version. Note that in Python 3, zip returns a generator, which actually may be just what you need, but if you absolutely need a list, you can just wrap the returned expression in a list() call.
Simplest:
def my_enumerate(items):
return list(enumerate(items))

how to replace the alphabetically smallest letter by 1, the next smallest by 2 but do not discard multiple occurrences of a letter?

I am using Python 3 and I want to write a function that takes a string of all capital letters, so suppose s = 'VENEER', and gives me the following output '614235'.
The function I have so far is:
def key2(s):
new=''
for ch in s:
acc=0
for temp in s:
if temp<=ch:
acc+=1
new+=str(acc)
return(new)
If s == 'VENEER' then new == '634335'. If s contains no duplicates, the code works perfectly.
I am stuck on how to edit the code to get the output stated in the beginning.
Note that the built-in method for replacing characters within a string, str.replace, takes a third argument; count. You can use this to your advantage, replacing only the first appearance of each letter (obviously once you replace the first 'E', the second one will become the first appearance, and so on):
def process(s):
for i, c in enumerate(sorted(s), 1):
## print s # uncomment to see process
s = s.replace(c, str(i), 1)
return s
I have used the built-in functions sorted and enumerate to get the appropriate numbers to replace the characters:
1 2 3 4 5 6 # 'enumerate' from 1 -> 'i'
E E E N R V # 'sorted' input 's' -> 'c'
Example usage:
>>> process("VENEER")
'614235'
One way would be to use numpy.argsort to find the order, then find the ranks, and join them:
>>> s = 'VENEER'
>>> order = np.argsort(list(s))
>>> rank = np.argsort(order) + 1
>>> ''.join(map(str, rank))
'614235'
You can use a regex:
import re
s="VENEER"
for n, c in enumerate(sorted(s), 1):
s=re.sub('%c' % c, '%i' % n, s, count=1)
print s
# 614235
You can also use several nested generators:
def indexes(seq):
for v, i in sorted((v, i) for (i, v) in enumerate(seq)):
yield i
print ''.join('%i' % (e+1) for e in indexes(indexes(s)))
# 614235
From your title, you may want to do like this?
>>> from collections import OrderedDict
>>> s='VENEER'
>>> d = {k: n for n, k in enumerate(OrderedDict.fromkeys(sorted(s)), 1)}
>>> "".join(map(lambda k: str(d[k]), s))
'412113'
As #jonrsharpe commented I didn't need to use OrderedDict.
def caps_to_nums(in_string):
indexed_replaced_string = [(idx, val) for val, (idx, ch) in enumerate(sorted(enumerate(in_string), key=lambda x: x[1]), 1)]
return ''.join(map(lambda x: str(x[1]), sorted(indexed_replaced_string)))
First we run enumerate to be able to save the natural sort order
enumerate("VENEER") -> [(0, 'V'), (1, 'E'), (2, 'N'), (3, 'E'), (4, 'E'), (5, 'R')]
# this gives us somewhere to RETURN to later.
Then we sort that according to its second element, which is alphabetical, and run enumerate again with a start value of 1 to get the replacement value. We throw away the alpha value, since it's not needed anymore.
[(idx, val) for val, (idx, ch) in enumerate(sorted([(0, 'V'), (1, 'E'), ...], key = lambda x: x[1]), start=1)]
# [(1, 1), (3, 2), (4, 3), (2, 4), (5, 5), (0, 6)]
Then map the second element (our value) sorting by the first element (the original index)
map(lambda x: str(x[1]), sorted(replacement_values)
and str.join it
''.join(that_mapping)
Ta-da!

How to write a function to rearrange a list according to the dictionary of index

How to write a function to rearrange a list according to the dictionary of index in python?
for example,
L=[('b',3),('a',2),('c',1)]
dict_index={'a':0,'b':1,'c':2}
I want a list of :
[2,3,1]
where 2 is from 'a',3 is from 'b' and 1 is from 'c', but rearrange only the number in L according to the dict_index
Try this (edited with simpler solution):
L=[('b',3),('a',2),('c',1)]
dict_index={'a':0,'b':1,'c':2}
# Creates a new empty list with a "slot" for each letter.
result_list = [0] * len(dict_index)
for letter, value in L:
# Assigns the value on the correct slot based on the letter.
result_list[dict_index[letter]] = value
print result_list # prints [2, 3, 1]
sorted and the .sort() method of lists take a key parameter:
>>> L=[('b',3),('a',2),('c',1)]
>>> dict_index={'a':0,'b':1,'c':2}
>>> sorted(L, key=lambda x: dict_index[x[0]])
[('a', 2), ('b', 3), ('c', 1)]
and so
>>> [x[1] for x in sorted(L, key=lambda x: dict_index[x[0]])]
[2, 3, 1]
should do it. For a more interesting example -- yours happens to match alphabetical order with the numerical order, so it's hard to see that it's really working -- we can shuffle dict_index a bit:
>>> dict_index={'a':0,'b':2,'c':1}
>>> sorted(L, key=lambda x: dict_index[x[0]])
[('a', 2), ('c', 1), ('b', 3)]
Using list comprehensions:
def index_sort(L, dict_index):
res = [(dict_index[i], j) for (i, j) in L] #Substitute in the index
res = sorted(res, key=lambda entry: entry[0]) #Sort by index
res = [j for (i, j) in res] #Just take the value
return res

How do I check the index of a an element in a list? (Python)

list = [('ba',4), ('hh',5), ('gg', 25)]
How do I do:
list.index('hh') ...and returns 1?
Then, how do I sort it by the 25, 5, 4?
What if I have 2 lists:
list1 = [('ba',4), ('hh',5), ('gg', 25)]
list2 = [('ja',40), ('hgh',88), ('hh', 2)]
how do I do a for each?
for item in l1:
if item[0] in l2[0 of the tuple]:
First of, don't use list as the name for a variable, as it shadows the built-in list function.
You can use enumerate to pair up list elements and their index:
>>> l = [('ba',4), ('hh',5), ('gg', 25)]
>>> [i for i, e in enumerate(l) if e[0] == 'hh']
[1]
For sorting you can use a lambda expression as shown by others, or you can pass an operator.itemgetter as the key argument to sorted:
>>> from operator import itemgetter
>>> sorted(l, key=itemgetter(1))
[('ba', 4), ('hh', 5), ('gg', 25)]
In-place sorting is also possible, using the sort method on lists:
>>> l.sort(key=itemgetter(1))
For the finding
>>> L = [('ba',4), ('hh',5), ('gg', 25)]
>>> [ i for i,l in enumerate(L) if l[0] == 'hh' ][0]
1
You need to decide what to do if it is found multiple times or not at all - the above will throw IndexError if not found and return the first if it is found multiple times.
For the sorting
>>> L = [('ba',4), ('hh',5), ('gg', 25)]
>>> sorted(L, key=lambda x: x[1])
[('ba', 4), ('hh', 5), ('gg', 25)]
I think Nick's sorting answer is good, but his find method unnecessarily iterates over the entire list, even after it has found a match. With a small change it can be fixed to stop iterating as soon as it finds the first element:
index = (i for i,l in enumerate(l) if l[0] == 'aa').next()
Or in Python 3:
index = next(i for i,l in enumerate(l) if l[0] == 'aa')
to sort the list u can use a custom sort method some thing like this
x = [('ba',4), ('hh',5), ('gg', 25)]
def sortMethod(x,y):
if x[1] < y[1]:return 1
elif x[1] > y[1]:return -1
else: return 0
print x #unsorted
x.sort(sortMethod)
print x #sorted
For the sort, you should use itemgetter
>>> import operator
>>> L = [('ba',4), ('hh',5), ('gg', 25)]
>>> sorted(L, key=operator.itemgetter(1))
[('ba', 4), ('hh', 5), ('gg', 25)]
you can also have your list in dictionary form
list1 = [('ba',4), ('hh',5), ('gg', 25)]
dict1 = dict(list1)
print dict1['hh']
5
dicts are faster then list if you need to search like that.
btw, overriding built-in type list to variables are not good idea list = [('ba',4), ('hh',5), ('gg', 25)].
from itertools import imap
def find(iterable, item, key=None):
"""Find `item` in `iterable`.
Return index of the found item or ``-1`` if there is none.
Apply `key` function to items before comparison with
`item`. ``key=None`` means an identity function.
"""
it = iter(iterable) if key is None else imap(key, iterable)
for i, e in enumerate(it):
if e == item:
return i
return -1
Example:
L = [('ba', 4), ('hh', 5), ('gg', 25)]
print find(L, 'hh', key=lambda x: x[0])
Output:
1
For the last question, convert list2 into a set:
>>> list1 = [('ba',4), ('hh',5), ('gg', 25)]
>>> list2 = [('ja',40), ('hgh',88), ('hh', 2)]
>>>
>>> wanted = set(a for (a,b) in list2)
>>> for x in list1:
... if x[0] in wanted:
... print x
...
('hh', 5)

Categories

Resources