'LIKE' function for Lists - python

Is there any equivalent 'LIKE' function(like in MySQL) for lists. for example;
This is my list:
abc = ['one', 'two', 'three', 'twenty one']
if I give the word "on", it should print the matching words from the list (in this case: 'one', 'twenty one') and if I give "fo", it should print False

You can use list comprehension:
[m for m in abc if 'on' in m]
This roughly translates to "for each element in abc, append element to a list if the element contains the substring 'on'"

>>> abc = ['one', 'two', 'three', 'twenty one']
>>> print [word for word in abc if 'on' in word]
['one', 'twenty one']

Would these list comprehensions suffice?
>>> abc = ['one', 'two', 'three', 'twenty one']
>>> [i for i in abc if 'on' in i]
['one', 'twenty one']
>>> [i for i in abc if 'fo' in i]
[]
You could wrap this in a function:
>>> def like(l, word):
... words = [i for i in abc if word in i]
... if words:
... print '\n'.join(words)
... else:
... print False
...
>>> like(abc, 'on')
one
twenty one
>>> like(abc, 'fo')
False
>>>

for x in abc:
if "on" in x:
print x
Or, as a function,
def like(str, search):
res = []
for x in search:
if str in x:
res.append(x)
return res

Related

How to remove items from list that have more then 20 characters?

I have a list, inside of list I have items. Some of items have more then 20 characters and I want to remove those items. But I don't want to remove items that have spaces. I provide minimal reproducible example...
This is a list...
some_list = ['one', 'two', 'three', 'black', 'verylongcharacterwords', 'very long character words']
I want to remove 'verylongcharacterwords', but I don't want to remove 'very long character words'.
This is wanted output...
new_list = ['one', 'two', 'three', 'black', 'very long character words']
Thanks in advance!
List comprehensions to the rescue:
>>> lst = ['one', 'two', 'three', 'black', 'verylongcharacterwords', 'very long character words']
>>> [l for l in lst if not any(len(w) > 20 for w in l.split())]
['one', 'two', 'three', 'black', 'very long character words']
>>>
Use a list comprehension with a condition.
new_list = [s for s in old_list if ' ' in s or len(s) <= 20]

How to make "seen" hash with python dict?

In Perl one can do this:
my %seen;
foreach my $dir ( split /:/, $input ) {
$seen{$dir}++;
}
This is a way to remove duplicates by keeping track of what has been "seen". In python you cannot do:
seen = {}
for x in ['one', 'two', 'three', 'one']:
seen[x] += 1
The above python results in KeyError: 'one'.
What is python-y way of making a 'seen' hash?
Use a defaultdict for getting this behavior. The catch is that you need to specify the datatype for defaultdict to work for even those keys which don't have a value:
In [29]: from collections import defaultdict
In [30]: seen = defaultdict(int)
In [31]: for x in ['one', 'two', 'three', 'one']:
...: seen[x] += 1
In [32]: seen
Out[32]: defaultdict(int, {'one': 2, 'three': 1, 'two': 1})
You can use a Counter as well:
>>> from collections import Counter
>>> seen = Counter()
>>> for x in ['one', 'two', 'three', 'one']: seen[x] += 1
...
>>> seen
Counter({'one': 2, 'three': 1, 'two': 1})
If all you need are uniques, just do a set operation: set(['one', 'two', 'three', 'one'])
You could use a set:
>>> seen=set(['one', 'two', 'three', 'one'])
>>> seen
{'one', 'two', 'three'}
If you unroll seen[x] += 1 into seen[x] = seen[x] + 1, the problem with your code is obvious: you're trying to access seen[x] before you've assigned to it. Instead, you need to check if the key exists first:
seen = {}
for x in ['one', 'two', 'three', 'one']:
if x in seen:
seen[x] += 1 # we've seen it before, so increment
else:
seen[x] = 1 # first time seeing x

Is there a way to use strip() on a list object? - python

For now I have an object of list like this:
lst = [None, None, 'one', None, 'two', None]
I am trying to perform strip() on it and get a result like this:
strip(lst)
>> ['one', None, 'two']
left_strip(lst)
>> ['one', None, 'two', None]
Is there a graceful way of doing that?
ps: thanks 4 #woockashek's advice, I've changed the lst
From [None, None, 'one','two', None] To [None, None, 'one', None, 'two', None]
To get a behaviour like left_strip you will need to import dropwhile from itertools:
>>> lst=[None, None, 'one', None, 'two', None, None]
>>> from itertools import dropwhile
>>> def left_strip(lst):
return list(dropwhile(lambda x : x is None, lst))
>>> left_strip(lst)
['one',None, 'two', None, None]
To get a behaviour like right_strip:
>>> from itertools import dropwhile
>>> def right_strip(lst):
return list(reversed(left_strip(reversed(lst))))
>>> right_strip(lst)
[None, None, 'one', None, 'two']
To get strip run both in sequence:
>>> left_strip(right_strip(lst))
['one', None, 'two']
You could use itertools.dropwhile to emulate an lstrip:
def lstrip(list):
return list(itertools.dropwhile(lambda x : x is None, list))
lst = [None, None, 'one', 'two', None]
lstrip(lst)
>> ['one', 'two', None]
rstrip could be implemented in the same way, but reversing the list before
and after using dropwhile
def rstrip(list):
return list(reversed(lstrip(reversed(list))))
there's a filter method:
lst = filter(None, lst)
But it will also remove 0 values if you have them on your list
To fix this behaviour you have to write your own filter method
def FilterNone(arg):
return arg is not None
filtered_list = filter(FilterNone, lst)
Here is a natural left_strip():
def left_strip(items):
for i,x in enumerate(items):
if x is not None: return items[i:]
return [] #in case all are None
For example,
>>> left_strip(lst)
['one', 'two', None]
you can use the filter like that:
lst = [None, None, 'one', 'two', None]
list(filter(None.__ne__, lst))
One way of doing it is:
def right_strip(lst):
for i in range(len(lst) - 1, -1, -1):
if lst[i] != None:
break
else:
return []
return lst[:i + 1]
def left_strip(lst):
for i in range(len(lst)):
if lst[i] != None:
break
else:
return []
return lst[i:]
def strip(lst):
return left_strip(right_strip(lst))
Did not get what you actually want to do ? You can use lst[2:4] and lst[2:].
Update: use set
if you want to have only values which are not 'None' then you use set as shown:
lst = [None, None, 'one', 'two', None]
lst1=[None]
print list(set(lst)-set(lst1))
You can try:
def left_strip(lst):
for i, e in enumerate(lst):
if e is not None:
return lst[i:]
return []
def right_strip(lst):
for i, e in reversed(list(enumerate(lst))):
if e is not None:
return lst[:i+1]
return []
print left_strip(right_strip(lst))
You can read more in remove None value from a list without removing the 0 value

Changing values of a list by getting them from a dictionary (Python)

So I have this list that looks like this:
['One', 'Two', 'Three', 'Four']
['Five', 'Six', 'Seven']
so, a list with 2 elements
lst = [['One', 'Two', 'Three', 'Four'], ['Five', 'Six', 'Seven']]
And then I have also a dictionary that I declared like this:
numberDict = dict()
numberDict["One"] = "First"
numberDict["Two"] = "Second"
numberDict["Three"] = "Third"
numberDict["Four"] = "Fourth"
numberDict["Five"] = "Fifth"
numberDict["Six"] = "Sixth"
numberDict["Seven"] = "Seventh"
My question: How can I get me list to look like this? To replace its values with the dictionary ones?
lst = [['First', 'Second', 'Third', 'Fourth'], ['Fifth', 'Sixth', 'Seventh']]
Use a list comprehension:
>>> list_of_list = [['One', 'Two', 'Three', 'Four'], ['Five', 'Six', 'Seven']]
>>> [[numberDict.get(value, "") for value in lst] for lst in list_of_list]
[['First', 'Second', 'Third', 'Fourth'], ['Fifth', 'Sixth', 'Seventh']]
As an aside, note that you can also initialize the numbersDict in a single go
>>> numbers_dict = {"One": "First",
... "Two": "Second",
... "Three": "Third",
... "Four": "Fourth",
... "Five": "Fifth",
... "Six": "Sixth",
... "Seven": "Seventh"}

Substitutions with elements from a list with re.sub?

What is the best way to perform substitutions with re.sub given a list? For example:
import re
some_text = 'xxxxxxx#yyyyyyyyy#zzzzzzzzz#'
substitutions = ['ONE', 'TWO', 'THREE']
x = re.sub('#', lambda i: i[0] substitutions.pop(0), some_text) # this doesn't actually work
The desired output would be:
some_text = 'xxxxxxxONEyyyyyyyyyTWOzzzzzzzzzTHREE'
You just have a syntax error in your lambda:
>>> substitutions = ['ONE', 'TWO', 'THREE']
>>> re.sub('#', lambda _: substitutions.pop(0), some_text)
'xxxxxxxONEyyyyyyyyyTWOzzzzzzzzzTHREE'
If you don't want to modify the list, you can wrap it an iterable.
>>> substitutions = ['ONE', 'TWO', 'THREE']
>>> subs = iter(substitutions)
>>> re.sub('#', lambda _: next(subs), some_text)
'xxxxxxxONEyyyyyyyyyTWOzzzzzzzzzTHREE'
One way (there's probably a better one, I don't really know Python) is to compile the regular expression, then use that sub instead:
import re
some_text = 'xxxxxxx#yyyyyyyyy#zzzzzzzzz#'
substitutions = ['ONE', 'TWO', 'THREE']
pattern = re.compile('#')
x = pattern.sub(lambda i: substitutions.pop(0), some_text)
Here's a demo.
The code is almost correct, it needs a slight correction of a syntax error:
import re
some_text = 'xxxxxxx#yyyyyyyyy#zzzzzzzzz#'
substitutions = ['ONE', 'TWO', 'THREE']
x = re.sub('#', lambda i: substitutions.pop(0), some_text) # the error was in the lambda function

Categories