building a boolean dictionary from 2 lists in python - python

I'm trying to make a dictionary with values 'True' or 'False' when comparing elements in 2 lists. This is probably a bit basic but I'm new to coding and I don't understand why it always assigns the 'True' value even though I can see its not true:
letters = [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z]
randomData = []
f = open('randomData.txt', 'r')
for line in f:
randomData.append(line.rstrip().split()[0])
f.close()
The 'randomData.txt' file looks like:
A'\t'0003'\t'0025'\t'chr1
B'\t'0011'\t'0021'\t'chr7
D'\t'0043'\t'0068'\t'chr3
F'\t'0101'\t'0119'\t'chr7
The randomData list should now look like:
['A','B','D','F']
I tried:
sameLetters = {}
i=0
while i < len(letters):
if letters[i] and randomData:
#append to dictionary
sameLetters[letters[i]] = 'True'
else:
#append to dictionary
sameLetters[letters[i]] = 'False'
i=i+1
print sameLetters
I expected something like:
{'A': 'True', 'B': 'True', 'C': 'False', 'D': 'True', 'E': 'False', 'F': 'True', 'G': 'False', etc
Instead all values in the dictionary are 'True'. Can anyone see the problem? Or give any pointers or explanations? Any help would be great, many thanks.

Perhaps you meant if letters[i] in randomData

I think you want to do something like:
sameLetters = {l: l in randomData for l in letters}
Your current attempt doesn't work because you check
if letters[i] and randomData:
# ^ should be in
and Python interprets both non-empty strings (letters[i]) and non-empty lists (randomData) as True.
Also, note that letters is already available in Python:
from string import ascii_uppercase
This is a string, but you can iterate through and index a string just like a list, and in will still work.

Seems like you only care about which letter appears in your random data, so why not use a set?
from string import ascii_uppercase
randomData = ['A', 'B', 'D', 'F', 'A']
appeared = set(ascii_uppercase).intersection(set(randomData))
print appeared
And later you can us it like this:
char = 'z'
if char in appeared:
print 'yes'
else:
print 'no'
EDIT:
Then how about this:)
from string import ascii_uppercase
randomData = ['A', 'B', 'D', 'F', 'A']
appeared = set(ascii_uppercase).intersection(set(randomData))
d = dict(zip(ascii_uppercase, (False,) * 26))
for key in appeared:
d[key] = True
print d

Related

python - check if word is in list full of strings and if there is print the words in an another list

so basically it would be like:
MyList=["Monkey","Phone","Metro","Boom","Feet"]
and let's say I have the input be m so Boom and Monkey and Metro would be put in a list like so
output >> ["Monkey","Metro","Feet"]
and if I would've had the input be f then the output would be
output >> ["Feet"]
and my question is how would I put this in a def? This is what I came up with
def Find(word,MyList):
MyList2=[]
count=0
for i in MyList:
count+=1
if i[count] == MyList2: ##(at first i did if i[0:10])
for x in range(1):
MyList2.append(i)
print(MyList2)
and then somewhere there should be
word=input("Word, please.")
and then
Find(word,MyList)
thanks in advance!
Try this :
def find_words(input_char, my_list):
ret_list = []
for i in my_list:
if input_char.lower() in i.lower():
ret_list.append(i)
return ret_list
MyList=["Monkey","Phone","Metro","Boom","Feet"]
input_char=input("Input a character :").strip() # get a character and strip spaces if any.
find_words(input_char, MyList) # call the function with arguments
Output for sample input "M :
Input a character :>? "M"
>>> ['Monkey', 'Metro', 'Boom']
(Almost) One liner:
>>> MyList=["Monkey","Phone","Metro","Boom","Feet"]
>>> target = input("Input string: ")
Input string: Ph
>>> print([i for i in MyList if target.lower() in i.lower()])
['Phone']
Generally in Python you don't want to be playing with indexes, iterators are the way to go.
The in keyword checks for substrings so it will work whether you provide only one character or a full string too (i.e. if you input Ph you'll get a list containing only Phone)
Depending on how efficient you want your search would be. Throwing in one more approach to build a dictionary like this
from collections import defaultdict
d = defaultdict(set)
for i in MyList:
chars = set(i)
for c in chars:
d[c].add(i)
Now, your dictionary looks like this
defaultdict(set,
{'o': {'Boom', 'Metro', 'Monkey', 'Phone'},
'k': {'Monkey'},
'e': {'Feet', 'Metro', 'Monkey', 'Phone'},
'M': {'Metro', 'Monkey'},
'y': {'Monkey'},
'n': {'Monkey', 'Phone'},
'h': {'Phone'},
'P': {'Phone'},
't': {'Feet', 'Metro'},
'r': {'Metro'},
'm': {'Boom'},
'B': {'Boom'},
'F': {'Feet'}})
Now, you can simply search within your dict with O(1) complexity
d[your_input_char]
Here is how you can use a list comprehension:
def Find(letter, MyList):
print([word for word in MyList if letter.lower() in word.lower()])
Find('m', ["Monkey","Phone","Metro","Boom","Feet"])
Output:
['Monkey', 'Metro', 'Boom']

Using python to determine if two strings are opposites given conditions

If we had certain conditions to fulfill such as
a is the opposite of b
c is the opposite of h
l is the opposite of r
the opposite of the string acl would be bhr
Do you guys think you can help me figure out how I would go about building a function that when given two strings will return a boolean that lets me know whether the given strings are opposite. for example input: opposite("ahl","bcr") would return True while ("ahl","bbr") would return False.
I would do it like a string compare, except that for every character, there would be a lookup table to get a translated value like so:
lookup = {
'a': 'b',
'c': 'h',
'l': 'r'
}
def opposite(one, two):
count = 0
if len(one) != len(two):
return False
for i in one:
if (lookup[i] != two[count] ):
return False
count += 1
return True
if __name__ == '__main__':
print opposite('acl', 'bhr')
If you have the lookup table, then this is a one-liner.
lookup = {
'a': 'b',
'c': 'h',
'l': 'r'
}
def opposite(str1, str2):
return [ lookup[c] for c in str1] == [ c for c in str2 ]
Depending on the actual situation (whether you know the first string contains only "acl" and the second only their opposites), you may need to have bidirectional lookup:
lookup = {
'a': 'b',
'c': 'h',
'l': 'r',
'b': 'a',
'h': 'c',
'r': 'l'
}
And if you want to have an exception raised when there are invalid characters in the input, you may change the function:
def opposite(str1, str2):
return [ lookup[c] for c in str1] == [ lookup[lookup[c]] for c in str2 ]

Breaking up a string by comparing characters/combinations of characters against a dictionary

What I would like to do is something like this:
testdictionary = {"a":1, "b":2, "c":3, "A":4}
list1 = []
list2 = []
keyval = 200
for char in string:
i = 0
y = "".join(list1)
while y in testdictionary:
list1.append(string[i])
i +=1
list2.append(y[:-1])
testdictionary[y] = keyval
keyval +=1
string = string[((len(list1))-1):]
list1 = []
So for a string "abcacababa" the desired output would be:
['ab', 'ca', 'cab', 'aba']
Or "AAAAA" would be
['A', 'AA'. 'AA']
Take abcacababa. Iterating through we get a which is in testdictionary so we append list1 again. This time we have ab which is not in the dictionary, so we add it as a key to testdictionary with a value of 200. Then doing the same process again, we add ca to testdictionary with a value of 201. Then since we have already added ca, the next value appended to list2 would be cab and so on.
What I am trying to do is take a string and compare each character against a dictionary, if the character is a key in the dictionary add another character, do this until it is not in the dictionary at which point add it to the dictionary and assign a value to it, keep doing this for the whole string.
There's obviously a lot wrong with this code, it also doesn't work. The i index being out of range but I have no idea how to approach this iteration. Also I need to add in an if statement to ensure the "leftovers" of the string at the end are appended to list2. Any help is appreciated.
I think I get it now #Boa. This code I believe works for abcacababa at least. As for leftovers, I think it's only possible to have a single 'leftover' key when the last key is in the test dictionary, so you just have to check after the loop if curr_key is not empty:
testdictionary = {"a":1, "b":2, "c":3, "A":4}
word = 'abcacababa'
key_val = 200
curr_key = ''
out_lst = []
let_ind = 0
for let in word:
curr_key += let
if curr_key not in testdictionary:
out_lst.append(curr_key)
testdictionary[curr_key] = key_val
key_val += 1
curr_key = ''
leftover = curr_key
print(out_lst)
print(testdictionary)
Output:
['ab', 'ca', 'cab', 'aba']
{'a': 1, 'A': 4, 'c': 3, 'b': 2, 'aba': 203, 'ca': 201, 'ab': 200, 'cab': 202}
Please let me know if anything is unclear. Also I think your second example with AAAAA should be ['AA', 'AAA'] instead of ['A', 'AA', 'AA']

Making sure only a particular group of characters are in a string

Is there any way to make sure that only the characters 'm' 'c' 'b' are in a string without resorting to regex?
For instance, if the user inputs 'm', the program will print 'Major'. If the user inputs 'mc', the program will print 'Major, Critical'.
So I want to make sure that if the user inputs something like 'mca', the program will print 'Not applicable'.
try:
if 'a' in args.findbugs:
if len(args.findbugs) > 1:
print 'findbugs: Not an applicable argument.'
else:
print 'FINDBUGS:ALL'
else:
if 'm' in args.findbugs:
print 'FINDBUGS:MAJOR'
if 'c' in args.findbugs:
print 'FINDBUGS:CRITICAL'
if 'b' in args.findbugs:
print 'FINDBUGS:BLOCKER'
except TypeError:
print "FINDBUGS: NONE"
Well, the simplest way from what you've described would be:
some_string = 'mca'
if set(some_string) <= {'m', 'c', 'b'}:
# The string contains only 'm', 'c', or 'b'.
else:
# The string 'mca' does not match because of 'a'.
Or, if you intend to require at least m, c, or b:
some_string = 'mca'
if set(some_string) & {'m', 'c', 'b'}:
# The string contains 'm', 'c', or 'b', so 'mca' will match.
NOTE: As pointed out by bgporter, the set literal notation is not available in Python versions less than 2.7. If support for those is required, use set(('m', 'c', 'b')).
This is a way to check it in linear time.
s = "blabla"
l = 'mcb'
print all(x in l for x in s)
Crude, but this would return what you need.
input not in itertools.combinations('mcb', 1) + itertools.combinations('mcb', 2) + itertools.combinations('mcb', 3)
arg_dict = {"m":'FINDBUGS:MAJOR',"c": 'FINDBUGS:CRITICAL',"b": 'FINDBUGS:BLOCKER'}
accepted =["m","c","b"]
user_args = "bccm"
if all(x in accepted for x in user_args):
for x in set(user_args):
print (arg_dict.get(x),
else:
print ("FINDBUGS: NONE")
FINDBUGS:CRITICAL FINDBUGS:BLOCKER FINDBUGS:MAJOR
If you want them in order sort the input:
accepted =["m","c","b"]
user_args = "bcm"
if all(x in accepted for x in user_args):
user_args = sorted(set(user_args),key=lambda x: accepted.index(x))
for x in user_args:
print "{} ".format((format(arg_dict.get(x)))),
else:
print ("FINDBUGS: NONE")
FINDBUGS:MAJOR FINDBUGS:CRITICAL FINDBUGS:BLOCKER

Sort a dictionary alphabetically, and print it by frequency

I am running python 2.7.2 on a mac.
I have a simple dictionary:
dictionary= {a,b,c,a,a,b,b,b,b,c,a,w,w,p,r}
I want it to be printed and have the output like this:
Dictionary in alphabetical order:
a 4
b 5
c 2
p 1
r 1
w 2
But what I'm getting is something like this...
a 1
a 1
a 1
a 1
b 1
.
.
.
w 1
This is the code I am using.
new_dict = []
for word in dictionary.keys():
value = dictionary[word]
string_val = str(value)
new_dict.append(word + ": " + string_val)
sorted_dictionary = sorted(new_dict)
for entry in sorted_dictionary:
print entry
Can you please tell me where is the mistake?
(By the way, I'm not a programmer but a linguist, so please go easy on me.)
What you're using is not a dictionary, it's a set! :)
And sets doesn't allow duplicates.
What you probably need is not dictionaries, but lists.
A little explanation
Dictionaries have keys, and each unique keys have their own values:
my_dict = {1:'a', 2:'b', 3:'c'}
You retrieve values by using the keys:
>>> my_dict [1]
'a'
On the other hand, a list doesn't have keys.
my_list = ['a','b','c']
And you retrieve the values using their index:
>>> my_list[1]
'b'
Keep in mind that indices starts counting from zero, not 1.
Solving The Problem
Now, for your problem. First, store the characters as a list:
l = ['a', 'b', 'c', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'a', 'w', 'w', 'p', 'r']
Next, we'll need to know what items are in this list:
items = []
for item in l:
if item not in items:
items.append(item)
This is pretty much equal to items = set(l) (the only difference is that this is a list). But just to make things clear, hope you understand what the code does.
Here is the content of items:
>>> items
['a', 'b', 'c', 'w', 'p', 'r']
With that done, we will use lst.count() method to see the number of a char's occurence in your list, and the built-in function sorted() to sort the items:
for item in sorted(items): #iterates through the sorted items.
print item, l.count(item)
Result:
a 4
b 5
c 2
w 2
p 1
r 1
Hope this helps!!
Let's start with the obvious, this:
dictionary= {a,b,c,a,a,b,b,b,b,c,a,w,w,p,r}
is not a dictionary. It is a set, and sets do not preserve duplicates. You probably meant to declare that as a list or a tuple.
Now, onto the meat of your problem: you need to implement something to count the items of your collection. Your implementation doesn't really do that. You could roll your own, but really you should use a Counter:
my_list = ['a','b','c','a','a','b','b','b','b','c','a','w','w','p','r']
from collections import Counter
c = Counter(my_list)
c
Out[19]: Counter({'b': 5, 'a': 4, 'c': 2, 'w': 2, 'p': 1, 'r': 1})
Now on to your next problem: dictionaries (of all types, including Counter objects) do not preserve key order. You need to call sorted on the dict's items(), which is a list of tuples, then iterate over that to do your printing.
for k,v in sorted(c.items()):
print('{}: {}'.format(k,v))
a: 4
b: 5
c: 2
p: 1
r: 1
w: 2
dictionary is something like this{key1:content1, key2:content2, ...} key in a dictionary is unique. then a = {1,2,3,4,5,5,4,5,6} is the set, when you print this out, you will notice that
print a
set([1,2,3,4,5,6])
duplicates are eliminated.
In your case, a better data structure you can use is a list which can hold multiple duplicates inside.
if you want to count the element number inside, a better option is collections.Counter, for instance:
import collections as c
cnt = c.Counter()
dict= ['a','b','c','a','a','b','b','b','b','c','a','w','w','p','r']
for item in dict:
cnt[item]+=1
print cnt
the results would be:
Counter({'b': 5, 'a': 4, 'c': 2, 'w': 2, 'p': 1, 'r': 1})
as you notice, the results become a dictionary here.
so by using:
for key in cnt.keys():
print key, cnt[key]
you can access the key and content
a 4
c 2
b 5
p 1
r 1
w 2
you can achieve what you want by modifying this a little bit. hope this is helpful
Dictionary cannot be defined as {'a','b'}. If it defined so, then it is an set, where you can't find duplicates in the list
If your defining a character, give it in quotes unless it is declared already.
You can't loop through like this for word in dictionary.keys():, since here dictionary is not a dictionary type.
If you like to write a code without using any builtin function, try this
input=['a','b','c','a','a','b','b','b','b','c','a','w','w','p','r']
dict={}
for x in input:
if x in dict.keys():
dict[x]=dict[x]+1
else:
dict[x]=1
for k in dict.keys():
print k, dict[k]
First, a dictionary is an unordered collection (i.e., it has no guaranteed order of its keys).
Second, each dict key must be unique.
Though you could count the frequency of characters using a dict, there's a better the solution. The Counter class in Python's collections module is based on a dict and is specifically designed for a task like tallying frequency.
from collections import Counter
letters = ['a', 'b', 'c', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'a', 'w', 'w', 'p', 'r']
cnt = Counter(letters)
print cnt
The contents of the counter are now:
Counter({'b': 5, 'a': 4, 'c': 2, 'w': 2, 'p': 1, 'r': 1})
You can print these conveniently:
for char, freq in sorted(cnt.items()):
print char, freq
which gives:
a 4
b 5
c 2
p 1
r 1
w 2

Categories