Convert list of strings into dictionary - python

I would like to convert a list of strings into a dictionary.
The list looks like such after I have split it into the seperate words:
[['ice'], ['tea'], ['silver'], ['gold']]
Which I want to convert to a dictionary which looks like such:
{ 1 : ['i', 'c', 'e']
2 : ['t','e','a']
3 : ['s','i','l','v','e','r']
4 : ['g','o','l','d']}
This is my code thus far:
import itertools
def anagram1(dict):
with open('words.txt', 'r') as f:
data = f.read()
data = data.split()
x = []
y = []
for word in data:
x1 = word.split()
x.append(x1)
for letters in word:
y1 = letters.split()
y.append(y1)
d = dict(itertools.zip_longest(*[iter(y)] * 2, fillvalue=""))
To which I receive the following error:
TypeError: 'dict' object is not callable

import pprint
l = [['ice'], ['tea'], ['silver'], ['gold']]
d = {idx: list(item[0]) for idx, item in enumerate(l, start =1)}
pprint.pprint(d)
{1: ['i', 'c', 'e'],
2: ['t', 'e', 'a'],
3: ['s', 'i', 'l', 'v', 'e', 'r'],
4: ['g', 'o', 'l', 'd']}

Following should do the job:
with open('file.txt', 'r') as f:
data = f.read()
data = data.split()
data_dict = {i:v for i,v in enumerate(data)}

Related

having only 1x value in a list in a dictionary

I want to create a dict with the occurence of the letter from a string as key and the letters which appear that many times as values.
My desired output with an example "occurence" should look like this:
{1: ['o', 'u', 'n'], 3: ['c'], 2: ['r', 'e']}
Right now it looks like this:
{1: ['o', 'u', 'n'], 3: ['c', 'c', 'c'], 2: ['r', 'r', 'e', 'e']}
My code right now:
letters = list(text)
new_dict = {}
for elements in list(text):
if letters.count(elements) not in new_dict:
new_dict[letters.count(elements)] = [elements]
else:
new_dict[letters.count(elements)].append(elements)
return new_dict
check if the letter is already in the dict and only if not add it:
letters = list(text) # this line is not needed
new_dict = {}
for elements in list(text): # `for elements in text:` works just fine
if letters.count(elements) not in new_dict: # text.count(...) works just like letters.count(...)
new_dict[letters.count(elements)] = [elements]
else: # can be simpified to `elif elements not in new_dict[...]:`
if elements not in new_dict[letters.count(elements)]: # check if the character is already present
new_dict[letters.count(elements)].append(elements)
return new_dict
btw. you don't have to convert the string to list to be iterable, support membership testing (a in b) or have a count method.
all of this also works with strings.
You can do it fairly succinctly using a Collections.Counter class to count the occurrences of each letter:
from collections import Counter
text = 'ouncccrree'
counter = Counter(text)
new_dict = {}
for k, v in counter.items():
new_dict[v] = new_dict.get(v, []) + [k]
print(new_dict) # -> {1: ['o', 'u', 'n'], 3: ['c'], 2: ['r', 'e']}

Python mapping values in a list by group

I have the following:
mylist = ['A','A','A','B','B','C']
colors = ['r','g','b','w','y']
I want all the same elements in mylist to get the same color, from the beginning of the color list, so the result would be like this:
result = ['r','r','r','g','g','b']
The colors, w and y would be ignored. Can't seem to get the mapping working correctly.
I have tried:
result = [[y for y in colors if set(mylist) == x] for x in mylist]
Edit: to make it more clear, ['r','g','b','w','y'] doesn't always need to be mapped to ABCDEF... mylist could have been ['cat','cat','cat','dog','dog','bird']
You may first create the mapping as a dict, then use it to get the result
mylist = ['A', 'A', 'A', 'B', 'B', 'C']
colors = ['r', 'g', 'b', 'w', 'y']
mapping = dict(zip(
sorted(set(mylist)),
colors
))
print(mapping) # {'A': 'r', 'B': 'g', 'C': 'b'}
result = [mapping[l] for l in mylist]
print(result) # ['r', 'r', 'r', 'g', 'g', 'b']
If you don't care about the order of colours:
color_map = dict(zip(set(mylist), colors))
result = [color_map[item] for item in mylist]
If you care about the order of colours:
from collections import OrderedDict
color_map = OrderedDict(zip(OrderedDict((item, True) for item in mylist), colors))
result = [color_map[item] for item in mylist]
You could use Counter to count how many times a value appears in your list.
Then use that mapping to fill your result list.
from collections import Counter
mylist = ['A','A','A','B','B','C']
colors = ['r','g','b','w','y']
result = []
for idx, (_,v) in enumerate( Counter(mylist).items() ):
result.extend( colors[idx] * v )
print(result)
Output:
['r', 'r', 'r', 'g', 'g', 'b']
Note: Requires Python > 3.7, otherwise the order of the dict is not guaranteed - this also applies to the other answers here that rely on dict.
For me the easiest way would be:
mylist = ['A', 'A', 'A', 'B', 'B', 'C']
colors = ['r', 'g', 'b', 'w', 'y']
result = []
for i, item in enumerate(sorted(set(mylist))): # sets doesn't maintain the order, so its sorted alphabetically
result.extend(colors[i] * mylist.count(item))
print(result)
I would suggest to use the dictionary instead to keep the mapping:
result = []
color_map = {}
idx = 0
for elt in mylist:
if elt not in color_map.keys():
color_map[elt] = colors[idx]
idx += 1
result.append(color_map[elt])
This also avoids iterating over the colors list separately.

Get sub-strings of a string

for e.g : string = 'AbcDEfGhIJK'
I want to fetch a list with :
['A','bc','DE','f','G','h','IJK']
I am trying to think of a logic for doing this, but so far no luck.
EDIT :
I don't know regex, so I just used loops
This is what I came up with, It doesn't give the last 'IJK' though
u_count = 0
l_count = 0
l_string = ''
u_string = ''
output = []
data = 'AbcDEfGhIJK'
for c in data:
if(c.isupper()):
if(l_count !=0):
output.append(l_string)
l_count = 0
l_string = ''
u_string += c
u_count += 1
if(c.islower()):
if(u_count !=0):
output.append(u_string)
u_count = 0
u_string = ''
l_string +=c
l_count += 1
print(output)
You could do that using itertools.groupby:
from itertools import groupby
string = 'AbcDEfGhIJK'
out = [''.join(group) for key, group in groupby(string, key=lambda c: c.islower())]
print(out)
# ['A', 'bc', 'DE', 'f', 'G', 'h', 'IJK']
Here, groupby will group the characters that give the same output for islower()
You could use a regex:
import re
text = 'AbcDEfGhIJK'
result = re.split('([a-z]+)', text)
print(result)
Output
['A', 'bc', 'DE', 'f', 'G', 'h', 'IJK']
The idea is to split the string on lower case letters '([a-z]+)', but keeping the splitting pattern.
str = 'AbcDEfGhIJK'
str=list(str)
for k,v in enumerate(str[:-1]):
joined=''.join([str[k],str[k+1]])
if joined.isupper() or joined.islower():
str[k+1]=joined
str[k]=''
str=[x for x in str if x!='']
print(str)
Output
['A', 'bc', 'DE', 'f', 'G', 'h', 'IJK']

how do you split elements of a list of list in python?

So I have a text file that looks like this:
abcd
efghij
klm
and I need to convert it into a two-dimensional list. And it should look like this:
[['a', 'b', 'c', 'd'],
['e', 'f', 'g', 'h', 'i', 'j'],
['k', 'l', 'm']]
so far I have managed to get this result:
[["abcd"], ["efghij"], ["klm"]]
Can anyone help me figure out what the next step should be?
Here is my code so far:
def readMaze(filename):
with open(filename) as textfile:
global mazeList
mazeList = [line.split() for line in textfile]
print mazeList
str.split() splits on whitespace. str.split('') splits each character separately. (apparently I'm misremembering, str.split('') throws a ValueError for "empty separator")
You'll just build a list from it.
text = """abcd
efghij
klm"""
mazelist = [list(line) for line in text.splitlines()]
# the splitlines call just makes it work since it's a string not a file
print(mazelist)
# [['a', 'b', 'c', 'd'], ['e', 'f', 'g', 'h', 'i', 'j'], ['k', 'l', 'm']]
Make a list of each line in the file:
with open('tmp.txt') as f:
z = [list(thing.strip()) for thing in f]
As explained above, you just need to build a list from the strings.
Assuming the string is held in some_text;
lines = some_text.split('\n')
my_list = []
for line in lines:
line_split = list(line)
my_list.append(line_split)
as one-liner;
my_list = map(lambda item: list(item), some_text.split('\n'))
should do the trick.

Python: how to print range a-z?

1. Print a-n: a b c d e f g h i j k l m n
2. Every second in a-n: a c e g i k m
3. Append a-n to index of urls{hello.com/, hej.com/, ..., hallo.com/}: hello.com/a hej.com/b ... hallo.com/n
>>> import string
>>> string.ascii_lowercase[:14]
'abcdefghijklmn'
>>> string.ascii_lowercase[:14:2]
'acegikm'
To do the urls, you could use something like this
[i + j for i, j in zip(list_of_urls, string.ascii_lowercase[:14])]
Assuming this is a homework ;-) - no need to summon libraries etc - it probably expect you to use range() with chr/ord, like so:
for i in range(ord('a'), ord('n')+1):
print chr(i),
For the rest, just play a bit more with the range()
Hints:
import string
print string.ascii_lowercase
and
for i in xrange(0, 10, 2):
print i
and
"hello{0}, world!".format('z')
for one in range(97,110):
print chr(one)
Get a list with the desired values
small_letters = map(chr, range(ord('a'), ord('z')+1))
big_letters = map(chr, range(ord('A'), ord('Z')+1))
digits = map(chr, range(ord('0'), ord('9')+1))
or
import string
string.letters
string.uppercase
string.digits
This solution uses the ASCII table. ord gets the ascii value from a character and chr vice versa.
Apply what you know about lists
>>> small_letters = map(chr, range(ord('a'), ord('z')+1))
>>> an = small_letters[0:(ord('n')-ord('a')+1)]
>>> print(" ".join(an))
a b c d e f g h i j k l m n
>>> print(" ".join(small_letters[0::2]))
a c e g i k m o q s u w y
>>> s = small_letters[0:(ord('n')-ord('a')+1):2]
>>> print(" ".join(s))
a c e g i k m
>>> urls = ["hello.com/", "hej.com/", "hallo.com/"]
>>> print([x + y for x, y in zip(urls, an)])
['hello.com/a', 'hej.com/b', 'hallo.com/c']
import string
print list(string.ascii_lowercase)
# ['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']
import string
print list(string.ascii_lowercase)
# ['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']
and
for c in list(string.ascii_lowercase)[:5]:
...operation with the first 5 characters
myList = [chr(chNum) for chNum in list(range(ord('a'),ord('z')+1))]
print(myList)
Output
['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']
list(string.ascii_lowercase)
['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']
Try:
strng = ""
for i in range(97,123):
strng = strng + chr(i)
print(strng)
import string
string.printable[10:36]
# abcdefghijklmnopqrstuvwxyz
string.printable[10:62]
# abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
#1)
print " ".join(map(chr, range(ord('a'),ord('n')+1)))
#2)
print " ".join(map(chr, range(ord('a'),ord('n')+1,2)))
#3)
urls = ["hello.com/", "hej.com/", "hallo.com/"]
an = map(chr, range(ord('a'),ord('n')+1))
print [ x + y for x,y in zip(urls, an)]
The answer to this question is simple, just make a list called ABC like so:
ABC = ['abcdefghijklmnopqrstuvwxyz']
And whenever you need to refer to it, just do:
print ABC[0:9] #prints abcdefghij
print ABC #prints abcdefghijklmnopqrstuvwxyz
for x in range(0,25):
if x % 2 == 0:
print ABC[x] #prints acegikmoqsuwy (all odd numbered letters)
Also try this to break ur device :D
##Try this and call it AlphabetSoup.py:
ABC = ['abcdefghijklmnopqrstuvwxyz']
try:
while True:
for a in ABC:
for b in ABC:
for c in ABC:
for d in ABC:
for e in ABC:
for f in ABC:
print a, b, c, d, e, f, ' ',
except KeyboardInterrupt:
pass
This is your 2nd question: string.lowercase[ord('a')-97:ord('n')-97:2] because 97==ord('a') -- if you want to learn a bit you should figure out the rest yourself ;-)
I hope this helps:
import string
alphas = list(string.ascii_letters[:26])
for chr in alphas:
print(chr)
About gnibbler's answer.
Zip -function, full explanation, returns a list of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables. [...] construct is called list comprehension, very cool feature!
# Assign the range of characters
first_char_start = 'a'
last_char = 'n'
# Generate a list of assigned characters (here from 'a' to 'n')
alpha_list = [chr(i) for i in range(ord(first_char), ord(last_char) + 1)]
# Print a-n with spaces: a b c d e f g h i j k l m n
print(" ".join(alpha_list))
# Every second in a-n: a c e g i k m
print(" ".join(alpha_list[::2]))
# Append a-n to index of urls{hello.com/, hej.com/, ..., hallo.com/}
# Ex.hello.com/a hej.com/b ... hallo.com/n
#urls: list of urls
results = [i+j for i, j in zip(urls, alpha_list)]
#print new url list 'results' (concatenated two lists element-wise)
print(results)
Another way to do it
import string
aalist = list(string.ascii_lowercase)
aaurls = ['alpha.com','bravo.com','chrly.com','delta.com',]
iilen = aaurls.__len__()
ans01 = "".join( (aalist[0:14]) )
ans02 = "".join( (aalist[0:14:2]) )
ans03 = "".join( "{vurl}/{vl}\n".format(vl=vlet,vurl=aaurls[vind % iilen]) for vind,vlet in enumerate(aalist[0:14]) )
print(ans01)
print(ans02)
print(ans03)
Result
abcdefghijklmn
acegikm
alpha.com/a
bravo.com/b
chrly.com/c
delta.com/d
alpha.com/e
bravo.com/f
chrly.com/g
delta.com/h
alpha.com/i
bravo.com/j
chrly.com/k
delta.com/l
alpha.com/m
bravo.com/n
How this differs from the other replies
iterate over an arbitrary number of base urls
cycle through the urls using modular arithmetic, and do not stop until we run out of letters
use enumerate in conjunction with list comprehension and str.format

Categories

Resources