Old maid card game - python-3.x

I am trying to write an old maid card game. Now I reach the stage of removing pairs, so if there are same numbers (2-10) and same letters(AKQJ), delete both of them. I have written several lines of code, but it does not work. Could you tell me why and help me fix it.
How can I identify the same number with different suits and delete both of them in the same list?
def x(alist):
n = '2345678910AKJQ'
a=[]
b=[]
for i in alist:
j = ''.join([k for k in i if k in n])
if not j in b:
a.append(i)
b.append(j)
return a

create a default dictionary creating a list, split the items according to last character (I used standard letters not symbols), and compose a listcomp with keys where there's only 1 value.
import re
from collections import defaultdict
deck = ['10H','AS','AH','4C','4S','5D']
dd = defaultdict(list)
for d in deck:
dd[d[:-1]].append(d[-1])
print([k for k,v in dd.items() if len(v)==1])
result:
['5', '10']

Related

Math-like way to define a set in Python: technical name [duplicate]

Can someone explain the last line of this Python code snippet to me?
Cell is just another class. I don't understand how the for loop is being used to store Cell objects into the Column object.
class Column(object):
def __init__(self, region, srcPos, pos):
self.region = region
self.cells = [Cell(self, i) for i in xrange(region.cellsPerCol)] #Please explain this line.
The line of code you are asking about is using list comprehension to create a list and assign the data collected in this list to self.cells. It is equivalent to
self.cells = []
for i in xrange(region.cellsPerCol):
self.cells.append(Cell(self, i))
Explanation:
To best explain how this works, a few simple examples might be instructive in helping you understand the code you have. If you are going to continue working with Python code, you will come across list comprehension again, and you may want to use it yourself.
Note, in the example below, both code segments are equivalent in that they create a list of values stored in list myList.
For instance:
myList = []
for i in range(10):
myList.append(i)
is equivalent to
myList = [i for i in range(10)]
List comprehensions can be more complex too, so for instance if you had some condition that determined if values should go into a list you could also express this with list comprehension.
This example only collects even numbered values in the list:
myList = []
for i in range(10):
if i%2 == 0: # could be written as "if not i%2" more tersely
myList.append(i)
and the equivalent list comprehension:
myList = [i for i in range(10) if i%2 == 0]
Two final notes:
You can have "nested" list comrehensions, but they quickly become hard to comprehend :)
List comprehension will run faster than the equivalent for-loop, and therefore is often a favorite with regular Python programmers who are concerned about efficiency.
Ok, one last example showing that you can also apply functions to the items you are iterating over in the list. This uses float() to convert a list of strings to float values:
data = ['3', '7.4', '8.2']
new_data = [float(n) for n in data]
gives:
new_data
[3.0, 7.4, 8.2]
It is the same as if you did this:
def __init__(self, region, srcPos, pos):
self.region = region
self.cells = []
for i in xrange(region.cellsPerCol):
self.cells.append(Cell(self, i))
This is called a list comprehension.

Calculating the occurrence of unknown values in a list

I very often face the following problem:
I have a list with unknown elements in it (but each element is of the same type, e.g.: str) and I want to count the occurrence of each element. Sometime I also want to do something with the occurrence values, so I usually store them in a dictionary.
My problem is, that I cannot "auto initialize" a dictionary with +=1, so I first I have to do a check, if the given element is still in the dictionary.
My usual go to solution:
dct = {}
for i in iterable:
if i in dct:
dct[i] += 1
else:
dct[i] = 1
Is there a simpler colution to this problem?
Yes! A defaultdict.
from collections import defaultdict
dct = defaultdict(int)
for i in iterable:
dict[i] += 1
You can auto-initialise with other types too:
Docs: https://docs.python.org/3.3/library/collections.html#collections.defaultdict
d = defaultdict(str)
d[i] += 'hello'
If you're just counting things, you could use a Counter instead:
from collections import Counter
c = Counter(iterable) # c is a subclass of dict

How to remove a character nested in a list?

I am given a sample string AABCAAADA. I then split it into 3 parts: AAB, CAA, ADA.
I have nested these 3 elements into a list. In each part, I should check whether a duplicate character is present and delete the duplicate character. I know strings are immutable, but is there any trick to do that?
Below is the sample approach I tried but I am unable to use del and pop method to delete that duplicate character.
s='AABCAAADA'
x = int(input())
l=[]
#for i in range(0,len(s),x):
for j in range(0,len(s),3):
l.append(s[j:j+3])
j=0
for i in range(0,len(s)//x):
for j in range(0,len(l[j])-1):
if(l[i][j] == l[i][j+1]):
pass
#need to remove the (j+1)th term if it is duplicate
The output should be AB, CA, AD.
delete duplicate character in nested list
from functools import reduce
l = ['AAB','CAA','ADA']
print([''.join(reduce(lambda a, b: a if b in a else a + b, s, '')) for s in l])
Or, for Python 3.6+:
print([''.join({a: 1 for a in s}) for s in l])
Both output:
['AB', 'CA', 'AD']

Creating a list of objects from a dictionary

So first of all I have a function that count words in a text file, and a program that creates a dictionary based on how many occurences of the word is in that text file. The program is
def counter (AllWords):
d = {}
for word in AllWords:
if word in d.keys():
d[word] = d[word] + 1
else:
d[word] = 1
return d;
f = open("test.txt", "r")
AllWords = []
for word in f.read().split():
AllWords.append(word.lower())
print(counter(AllWords))
Now given that dictionary, I want to create a list of objects such that the objects will have two instance variables, the word (string) and how many time it appears (integer). Any help is appreciated!
What about:
list(d.items())
It will create a list of tuples like:
[('Foo',3),('Bar',2)]
Or you can define your own class:
class WordCount:
def __init__(self,word,count):
self.word = word
self.count = count
and use list comprehension:
[WordCount(*item) for item in d.items()]
So here you create a list of WordCount objects.
Nevertheless, your counter(..) method is actually not necessary: Python already has a Counter:
from collections import Counter
which is "a dictionary with things" so to speak: you can simply construct it like:
from collections import Counter
Counter(allWords)
No need to reinvent to wheel to count items.
What about a quasi one-liner to do all the heavy lifting, using of course collections.Counter and the mighty str.split ?
import collections
with open("text.txt") as f:
c = collections.Counter(f.read().split())
Now c contains the couples: word,number of occurences of the word

How to create a dictionary from a file with multiple lines

I'm trying to create a dictionary from multiple lines in a file, for i.e.
grocery store
apples
banana
bread
shopping mall
movies
clothing stores
shoe stores
What I'm trying to do is make the first row of each section (i.e. grocery store and shopping mall) the keys and everything underneath (apple, banana, bread & movies, clothing stores, shoe stores respectively) the values. I've been fiddling around with the readline approach + while loop, but I haven't been able to figure it out. If anyone knows, please help. Thanks.
One solution is to store in a variable the boolean value for whether you're at the start of a section. I don't want to give away the exciting (?) ending, but you could start with is_first=True.
OK, I guess I do want to give away the ending after all. Here's what I had in mind, more or less:
with open(fname) as f:
content = f.readlines()
is_first = True
d = {}
for line in content:
if line == '\n':
is_first = True
elif is_first:
key = line
is_first = False
else:
if key not in d:
d.put(key, '')
d.put(key, d.get(key) + line)
is_first = False
I find it easier to plan the code that way. Of course you could also solve this without an is_first variable, especially if you've already gone through the exercise of doing it with an is_first variable. I think the following is correct, but I wasn't incredibly careful:
with open(fname) as f:
content = f.readlines()
d = {}
while content:
key, content = content[0], content[1:]
if key != '\n':
value, content = content[0], content[1:]
while value != '\n':
if key not in d:
d.put(key, '')
d.put(key, d.get(key) + value)
value, content = content[0], content[1:]
#minopret has already given a pedagogically useful answer, and one that's important for beginners to understand. In a sense, even some more seemingly-sophisticated approaches are often doing that under the hood -- using a kind of state machine, I mean -- so it's important to know.
But for the heck of it, I'll describe a higher-level approach. There's a handy function itertools.groupby which groups sequences into contiguous groups. In this case, we can define a group by a bunch of lines which aren't all empty -- bool(line) is False if the line is empty and True otherwise, and then build a dict from them.
from itertools import groupby
with open("shopdict.txt") as fin:
stripped = map(str.strip, fin)
grouped = (list(g) for k,g in groupby(stripped, bool) if k)
d = {g[0]: g[1:] for g in grouped}
from itertools import groupby
with open("shopdict.txt") as fin:
stripped = map(str.strip, fin)
d = {k: g for b, (k, *g) in groupby(stripped, bool) if b}
And here's a way just using for loops
d={}
with open("shopdict.txt") as fin:
for key in fin:
key = key.strip()
d[key] = []
for item in fin:
if item.isspace():
break
d[key].append(item.strip())

Resources