I am trying to add "!" after every variable in a list.
But my code only adds the series of "!" after the initial list.
For example:
lst = [1,2,3,4]
def addmark(lst):
emptylst = []
for n in range(0, len(lst)):
lst.append("!")
return lst
This would return [1,2,3,4,"!", "!", "!", "!"]
I want to reuturn [1, "!", 2, "!", 3, "!", 4, "!"]
def addmark(lst):
emptylst = []
for i in lst:
emptylst.append(i)
emptylst.append("!")
return emptylst
An alternative to the accepted answer using itertools:
from itertools import chain, repeat
lst = [1, 2, 3]
marker = repeat("!")
list(chain.from_iterable(zip(lst, marker)))
>>> [1, '!', 2, '!', 3, '!']
Using insert:
list.insert (i, x)
Insert an item at a given position. The first
argument is the index of the element before which to insert, so
a.insert(0, x) inserts at the front of the list, and a.insert(len(a),
x) is equivalent to a.append(x).
Reference: docs.python.org/2/tutorial/datastructures
Code:
def addmark(lst):
add = 0 # needed cause after every insertion of '!' the position where you want to add the next '!' changes
for i in range (1,len(lst)+1): # (start: adding after ls[0], finish: adding after the last element)
lst.insert(i+add, '!')
add += 1
return lst
this is code
#!/usr/bin/env python
# coding:utf-8
'''黄哥Python'''
def addmark(lst):
result = []
for i, item in enumerate(lst):
result.append(item)
result.append("!")
return result
if __name__ == '__main__':
lst = [1,2,3,4]
print addmark(lst)
create a list of lists then flatten
lst = [1,2,3,4]
lst2 = [[i,'!'] for i in lst]
lst3 = [item for sublist in lst2 for item in sublist]
print lst2
print lst3
>>> [[1, '!'], [2, '!'], [3, '!'], [4, '!']]
>>> [1, '!', 2, '!', 3, '!', 4, '!']
as a one liner:
lst = [1,2,3,4]
lst2 = [item for sublist in [[i,'!'] for i in lst] for item in sublist]
print lst2
>>> [1, '!', 2, '!', 3, '!', 4, '!']
Related
I am trying to remove any strings from this list of strings if their length is greater than 5. I don't know why it is only removing what seems to be random strings. Please help. The item for sublist part of the code just changes the list of lists, into a normal list of strings.
list2 = [['name'],['number'],['continue'],['stop'],['signify'],['tester'],['racer'],['stopping']]
li = [item for sublist in list2 for item in sublist]
var=0
for words in li:
if len(li[var])>5:
li.pop()
var+=1
print(li)
The output is: ['name', 'number', 'continue', 'stop', 'signify']
Just include the check when flattening the list:
list2 = [['name'],['number'],['continue'],['stop'],['signify'],['tester'],['racer'],['stopping']]
li = [item for sublist in list2 for item in sublist if len(item) <= 5]
['name', 'stop', 'racer']
You can use a list comprehension to build a new list with only items that are 5 or less in length.
>>> l = ['123456', '123', '12345', '1', '1234567', '12', '1234567']
>>> l = [x for x in l if len(x) <= 5]
>>> l
['123', '12345', '1', '12']
list(filter(lambda x: len(x[0]) <= 5, list2))
I have a list of lists with a certain range:
l = [["this", "is", "a"], ["list", "of"], ["lists", "that", "i", "want"], ["to", "copy"]]
And a list of words:
words = ["lorem", "ipsum", "dolor", "sit", "amet", "id", "sint", "risus", "per", "ut", "enim", "velit", "nunc", "ultricies"]
I need to create an exact replica of the list of lists, but with random terms picked from the other list.
This was the first thing that came to mind, but no dice.
for random.choice in words:
for x in list:
for y in x:
y = random.choice
Any ideas? Thank you in advance!
You can use list comprehensions for this:
import random
my_list = [[1, 2, 3], [5, 6]]
words = ['hello', 'Python']
new_list = [[random.choice(words) for y in x] for x in my_list]
print(new_list)
Output:
[['Python', 'Python', 'hello'], ['Python', 'hello']]
This is equivalent to:
new_list = []
for x in my_list:
subl = []
for y in x:
subl.append(random.choice(words))
new_list.append(subl)
With your example data:
my_list = [['this', 'is', 'a'], ['list', 'of'],
['lists', 'that', 'i', 'want'], ['to', 'copy']]
words = ['lorem', 'ipsum', 'dolor', 'sit', 'amet', 'id', 'sint', 'risus',
'per', 'ut', 'enim', 'velit', 'nunc', 'ultricies']
new_list = [[random.choice(words) for y in x] for x in my_list]
print(new_list)
Output:
[['enim', 'risus', 'sint'], ['dolor', 'lorem'], ['sint', 'nunc', 'ut', 'lorem'], ['ipsum', 'amet']]
You're not storing the values back into your lists. Try:
for i in range(0, len(list)):
subl = list[i]
for n in range(0, len(subl)):
list[i][n] = random.choice(words)
You should flatten your list of lists, then shuffle, then rebuild. Example:
import random
def super_shuffle(lol):
sublist_lengths = [len(sublist) for sublist in lol]
flat = [item for sublist in lol for item in sublist]
random.shuffle(flat)
pos = 0
shuffled_lol = []
for length in sublist_lengths:
shuffled_lol.append(flat[pos:pos+length])
pos += length
return shuffled_lol
print super_shuffle([[1,2,3,4],[5,6,7],[8,9]])
Prints:
[[7, 8, 5, 6], [9, 1, 3], [2, 4]]
This randomizes across ALL the lists, not just within a single sublist and guarantees no dups.
If a have a list like this:
[['welcome','a1'],['welcome','a1'],['hello','a2'],['hello','a3']]
and I want to return something like this:
[['welcome','a1', 2],['hello','a2', 1],['hello','a3', 1]]
If the same pair of strings in a sublist is encountered, increment the count
What I have so far:
counter = 0
for i in mylist:
counter += 1
if i[0]== i[0]:
if i[1] == i[1]:
counter -= 1
ouptut.append([mylist, counter])
I'm new at this and I appreciate your help!
Use a set here to get only unique items:
>>> lis = [['welcome','a1'],['welcome','a1'],['hello','a2'],['hello','a3']]
>>> [list(x) + [1] for x in set(map(tuple, lis))]
>>> [['welcome', 'a1', 1], ['hello', 'a3', 1], ['hello', 'a2', 1]]
Explanation:
Set always returns unique items from an iterable or iterator, but as sets can only contain immutable item so you should convert them to a tuple first. A verbose version of the above code, only difference is that will also preserve the original or
>>> lis = [['welcome','a1'],['welcome','a1'],['hello','a2'],['hello','a3']]
>>> s = set()
>>> for item in lis:
... tup = tuple(item) #covert to tuple
... s.add(tup)
>>> s
set([('welcome', 'a1'), ('hello', 'a3'), ('hello', 'a2')])
Now use a list comprehension to get the expected output:
>>> [list(item) + [1] for item in s]
[['welcome', 'a1', 1], ['hello', 'a3', 1], ['hello', 'a2', 1]]
If the order of items matter(sets don't preserve order), then use this:
>>> seen = set()
>>> ans = []
>>> for item in lis:
... tup = tuple(item)
... if tup not in seen:
... ans.append(item + [1])
... seen.add(tup)
...
>>> ans
[['welcome', 'a1', 1], ['hello', 'a2', 1], ['hello', 'a3', 1]]
I am not sure what's the point of using 1 here.
I have an array consisting of a set of lists of strings (can assume each string is a single word).
I want an efficient way, in Python, to count pairs of words in this array.
It is not collocation or bi-grams, as each word in the pair may be in any position on the list.
It's unclear how your list is, Is it something like:
li = ['hello','bye','hi','good','bye','hello']
If so the solution is simple:
In [1342]: [i for i in set(li) if li.count(i) > 1]
Out[1342]: ['bye', 'hello']
Otherwise if it is like:
li = [['hello'],['bye','hi','good'],['bye','hello']]
Then:
In [1378]: f = []
In [1379]: for x in li:
.......... for i in x:
.......... f.append(i)
In [1380]: f
Out[1380]: ['hello', 'bye', 'hi', 'good', 'bye', 'hello']
In [1381]: [i for i in set(f) if f.count(i) > 1]
Out[1381]: ['bye', 'hello']
>>> from itertools import chain
>>> from collections import Counter
>>> L = [['foo', 'bar'], ['apple', 'orange', 'mango'], ['bar']]
>>> c = Counter(frozenset(x) for x in combinations(chain.from_iterable(L), r=2))
>>> c
Counter({frozenset(['mango', 'bar']): 2, frozenset(['orange', 'bar']): 2, frozenset(['foo', 'bar']): 2, frozenset(['bar', 'apple']): 2, frozenset(['orange', 'apple']): 1, frozenset(['foo', 'apple']): 1, frozenset(['bar']): 1, frozenset(['orange', 'mango']): 1, frozenset(['foo', 'mango']): 1, frozenset(['mango', 'apple']): 1, frozenset(['orange', 'foo']): 1})
In Python, I want to convert a list of strings:
l = ['sam','1','dad','21']
and convert the integers to integer types like this:
t = ['sam',1,'dad',21]
I tried:
t = [map(int, x) for x in l]
but is showing an error.
How could I convert all intable strings in a list to int, leaving other elements as strings?
My list might be multi-dimensional. A method which works for a generic list would be preferable:
l=[['aa','2'],['bb','3']]
I'd use a custom function:
def try_int(x):
try:
return int(x)
except ValueError:
return x
Example:
>>> [try_int(x) for x in ['sam', '1', 'dad', '21']]
['sam', 1, 'dad', 21]
Edit: If you need to apply the above to a list of lists, why didn't you converted those strings to int while building the nested list?
Anyway, if you need to, it's just a matter of choice on how to iterate over such nested list and apply the method above.
One way for doing that, might be:
>>> list_of_lists = [['aa', '2'], ['bb', '3']]
>>> [[try_int(x) for x in lst] for lst in list_of_lists]
[['aa', 2], ['bb', 3]]
You can obviusly reassign that to list_of_lists:
>>> list_of_lists = [[try_int(x) for x in lst] for lst in list_of_lists]
How about using map and lambda
>>> map(lambda x:int(x) if x.isdigit() else x,['sam','1','dad','21'])
['sam', 1, 'dad', 21]
or with List comprehension
>>> [int(x) if x.isdigit() else x for x in ['sam','1','dad','21']]
['sam', 1, 'dad', 21]
>>>
As mentioned in the comment, as isdigit may not capture negative numbers, here is a refined condition to handle it notable a string is a number if its alphanumeric and not a alphabet :-)
>>> [int(x) if x.isalnum() and not x.isalpha() else x for x in ['sam','1','dad','21']]
['sam', 1, 'dad', 21]
I would create a generator to do it:
def intify(lst):
for i in lst:
try:
i = int(i)
except ValueError:
pass
yield i
lst = ['sam','1','dad','21']
intified_list = list(intify(lst))
# or if you want to modify an existing list
# lst[:] = intify(lst)
If you want this to work on a list of lists, just:
new_list_of_lists = map(list, map(intify, list_of_lists))
For multidimenson lists, use recursive technique may help.
from collections import Iterable
def intify(maybeLst):
try:
return int(maybeLst)
except:
if isinstance(maybeLst, Iterable) and not isinstance(lst, str):
return [intify(i) for i in maybeLst] # here we call intify itself!
else:
return maybeLst
maybeLst = [[['sam', 2],'1'],['dad','21']]
print intify(maybeLst)
Use isdigit() to check each character in the string to see if it is a digit.
Example:
mylist = ['foo', '3', 'bar', '9']
t = [ int(item) if item.isdigit() else item for item in mylist ]
print(t)
Use a list comprehension to validate the numeracy of each list item.
str.isnumeric won't pass a negative sign
Use str.lstrip to remove the -, check .isnumeric, and convert to int if it is.
Alternatively, use str.isdigit in place of .isnumeric.
Keep all values in the list
l = ['sam', '1', 'dad', '21', '-10']
t = [int(v) if v.lstrip('-').isnumeric() else v for v in l]
print(t)
>>> ['sam', 1, 'dad', 21, -10]
Remove non-numeric values
l = ['sam', '1', 'dad', '21', '-10']
t = [int(v) for v in t if v.lstrip('-').isnumeric()]
print(t)
>>> [1, 21, -10]
Nested list
l = [['aa', '2'], ['bb', '3'], ['sam', '1', 'dad', '21', '-10']]
t = [[int(v) if v.lstrip('-').isnumeric() else v for v in x] for x in l]
print(t)
>>> [['aa', 2], ['bb', 3], ['sam', 1, 'dad', 21, -10]]