How to append lists in a dictionary in Python? - python

Hey everyone this code is working fine just one thing to deal with. It overwrites the multiple entries against a key. I need to avoid the overwriting and to save all those entries. Can you help me in this please?
#!/usr/bin/python
import sys
import fileinput
#trys to create dictionary from african country list
dic = {}
for line in sys.stdin:
lst = line.split('|')
links = lst[4].split()
new=links[0] + ' ' + links[len(links)-1]
dic[new]=lst[4] # WARNING: overwrites multiple entriess at the moment! :)
for newline in fileinput.input('somefile.txt'):
asn = newline.split()
new = asn[0] + ' ' + asn[1]
if new in dic:
print "found from " + asn[0] + " to " + asn[1]
print dic[new]
Note: Sys.stdin takes a string in the following format;
1.0.0.0/24|US|158.93.182.221|GB|7018 1221 3359 3412 2543 1873

You've got a number of problems with your code. The simplest way to do what you describe is to use a defaultdict, which gets rid of the explicit if and has_key (which you should replace by new in dic anyway):
#trys to create dictionary from african country list
from collections import defaultdict
dic = defaultdict(list) # automatically creates lists to append to in the dict
for line in sys.stdin:
mylist = line.split('|') # call it mylist instead of list
links = mylist[4].split()
new = links[0] + ' ' + links[-1] # can just use -1 to reference last item
dic[new].append(mylist[4]) # append the item to the list in the dict
# automatically creates an empty list if needed
See eryksun's comment on Gerrat's answer if you're on an old version of Python without defaultdict.

There is no method called appendlist. use append:
dic[dic[new]].append(list[4])
Also, it's inadvisable to use list as a variable name.
It is a builtin in python.
Also, this entire section of code:
if ( dic.has_key(new))
dic[dic[new]].appendlist(list[4])
else:
dic[dic[new]] = [list[4]]
should instead probably be:
if new in dic: # this is the preferrable way to test this
dic[new].append(list[4])
else:
dic[new] = [list[4]]

Related

Python Beginner - How do I recall the deleted items from a list

I am a python beginner and I was wondering once the item on the list is replaced, can it be recalled back ?
Friends=["Jen","Lam","Sam","Song"]
print (Friends)
#replace a list item
Friends[0] = "Ken"
print (Friends)
How should I write the line if I wanna say that Jen is replaced by Ken in python by not directly writing print("Jen") out and using a variable.
Keep track of Friends[0] before replacing it.
i.e.
friends=["Jen","Lam","Sam","Song"]
print(Friends)
replaced = friends[0]
friends[0] = "Ken"
print(replaced + " was replaced by " + friends[0])
You can also use pop and insert.
friends=["Jen","Lam","Sam","Song"]
print(friends)
replaced = friends.pop(0)
friends.insert(0, "Ken")
print(replaced + " was replaced by " + friends[0])
Not that I know of. But you could just make a copy of the list and use that to change it back to what it was by getting the old name from that list.
Friends=["Jen","Lam","Sam","Song"]
replaceName = Friends[0]
newName= "ken"
Friends [0] = newName
print(replaceName, " was replaced by ", newName)
print(Friends)
You would have to store "jen" as a variable if you wanted to replace the name with "ken" in the list.
Something like this:
replace = Friends[0]
Friends[0] = "ken"
after these two lines, when you print(Friends[0]) it would return "Ken" but you could print(replace) and it would print "jen"
You can also utilize other list methods to .append Ken to the list to have both names in the list.
This site is very helpful for all the different list methods and how to use them!
https://docs.python.org/3.9/tutorial/datastructures.html#the-del-statement
Friends = ["Jen", "Lam", "Sam", "Song"]
friend_to_delete = Friends[0]
print (Friends)
Friends[0] = "Ken"
print (Friends)
print(friend_to_delete, 'was replaced by', Friends[0])
Very simple answer:
Friends=['Jen', 'Lam', 'Sam', 'Song']
print (Friends)
Friends.append('Ken') #This adds in the string('Ken') without directly altering the list
Friends.reverse() #This reverses the order in your list
Friends.remove('Jen') #This removes the string ('Jen') from your list
#Note you can also use Friends.pop(4) to remove the string 'Jen' since its reversed
print(Friends)

How can I store this in a dictionary?

I must write a dictionary. This is my first time doing it and I can't wrap my head around it. The first 5 element should be the key to it and the rest the value.
for i in verseny:
if i not in eredmeny:
eredmeny[i] = 1
else:
eredmeny[i] += 1
YS869 CCCADCADBCBCCB this is a line from the hw. This YS869 should be the key and this CCCADCADBCBCCB should be the value.
The problem is that I can't store them in a dictionary. I'm grinding gears here but getting nowhere.
Assuming that erdemeny is your dictionary name and that verseny is the list that includes your values and keys strings. This should do it:
verseny = ['YS869 CCCADCADBCBCCB', 'CS769 CCCADCADBCBCCB', 'BS869 CCCADCADBCBCCB']
eredmeny = {}
for i in verseny:
key, value = i.split(' ')[0], i.split(' ')[1]
if key not in eredmeny.keys():
eredmeny[key] = value
else:
eredmeny[key].append(value)
I'm not really understanding the question well, but an easy way to do the task at hand would be converting the list into a string and then using split():
line = 'YS869 CCCADCADBCBCCB'
words = l.split()
d = {ls[0]: ls[1]}
print(d)
this is the basic skill in python. I hope you can refer to the existing materials. As your example, the following demonstrations are given:
line = 'YS869 CCCADCADBCBCCB'
dictionary = {}
dictionary[line[:4]] = line[5:]
print(dictionary) # {'YS86': ' CCCADCADBCBCCB'}

Converting a list of dicts to wiki-format

I have a list of dicts that looks like this (might look like this, I really have no idea upfront what data they contain):
data = [
{'k1': 'v1-a', 'k2': 'v2-a', 'k3': 'v3-a'},
{'k1': 'v1-b', 'k3': 'v3-b'},
{'k1': 'v1-c', 'k2': 'v2-c', 'k3': 'v3-c'},
{'k1': 'v1-d', 'k2': 'v2-d', 'k3': 'v3-d'}
]
The goal is to make it into a string that looks like this:
||k1||k2||k3||
|v1-a|v2-a|v3-a|
|v1-b||v3-b|
|v1-c|v2-c|v3-c|
|v1-d|v2-d|v3-d|
This is for the confluence wiki format.
The problem in itself is not that complicated, but the solution I come up with is so ugly that I almost don't want to use it.
What I got currently is this:
from pandas import DataFrame
// data = ...
df = DataFrame.from_dict(data).fillna('')
body = '||{header}||\n{data}'.format(
header='||'.join(df.columns.values.tolist()),
data='\n'.join(['|{}|'.format('|'.join(i)) for i in df.values.tolist()])
)
Which isn't just ugly, it depends on pandas, which is huge (I don't want to depend on this library just for this)!
The solution above would work without pandas if there was a good way of getting the list of headers, and list of list of values from the dict. But python 2 does't guaranty dict order, so I can't count on .values() giving me the correct info.
Is there anything in itertools or collections I've been missing out of?
This works for me in Python 3 and 2.7. Try it: https://repl.it/repls/VividMediumturquoiseAlbino
all_keys = sorted({key for dic in data for key in dic.keys()})
header = "||" + "||".join(all_keys) + "||"
lines = [header]
for row in data:
elems_on_row = [row.get(key, "") for key in all_keys]
current_row = "|" + "|".join(elems_on_row) + "|"
lines.append(current_row)
wikistr = "\n".join(lines)
print(wikistr)
One approach would be to use csv.DictWriter to handle the formatting, with StringIO to collect the input and defaultdict to do a bit of creative cheating. Whether or not this is prettier is up for debate.
from StringIO import StringIO
from collections import defaultdict
from csv import DictWriter
output = StringIO()
keys = list(set(key for datum in data for key in datum.keys()))
header = '|'.join('|{}|'.format(key) for key in keys)
output.write(header + '\n')
fields = [''] + keys + [''] # provides empty fields for starting and ending |
writer = DictWriter(output, fields, delimiter = '|')
for row in data:
writer.writerow(defaultdict(str, **row)) # fills in the empty fields
output.seek(0)
result = output.read()
How it works
Create the list of headers by making a set containing all keys that are in any one of your dictionaries.
Make a DictWriter that uses '|' for its delimiter, to get the pipes between entries.
Add empty-string headers at the beginning and end, so that the beginning and ending pipes will get written.
Use a defaultdict to supply the empty beginning and ending values, since they're not in the dictionaries.
The answer in pure Python is to walk the list and therefore every dictionary twice.
In the first run you can collect all distinct keys and in the second run you can build your wiki formatted string output.
Let's start by collecting the keys where we can use a set as storage:
keys = set()
for dict_ in data:
keys.update(set(dict_.keys())
keys = sorted(keys)
Now that we have the set of unique keys, we can run through the list again for the output:
wiki_output = ''
wiki_output = '||' + '||'.join(keys) + '||'
for dict_ in data:
for key in keys:
wiki_output += '|' + dict_.get(key, '')
wiki_output += '|\n'
There we go...

Writing out comma separated values in a single cell in spreadsheet

I am cataloging attribute fields for each feature class in the input list, below, and then I am writing the output to a spreadsheet for the occurance of the attribute in one or more of the feature classes.
import arcpy,collections,re
arcpy.env.overwriteOutput = True
input = [list of feature classes]
outfile= # path to csv file
f=open(outfile,'w')
f.write('ATTRIBUTE,FEATURE CLASS\n\n')
mydict = collections.defaultdict(list)
for fc in input:
cmp=[]
lstflds=arcpy.ListFields(fc)
for fld in lstflds:
cmp.append(fld.name)
for item in cmp:
mydict[item].append(fc)
for keys, vals in mydict.items():
#remove these characters
char_removal = ["[","'",",","]"]
new_char = '[' + re.escape(''.join(char_removal)) + ']'
v=re.sub(new_char,'', str(vals))
line=','.join([keys,v])+'\n'
print line
f.write(line)
f.close()
This code gets me 90% of the way to the intended solution. I still cannot get the feature classes(values) to separate by a comma within the same cell(being comma delimited it shifts each value over to the next column as I mentioned). In this particular code the "v" on line 20(feature class names) are output to the spreadsheet, separated by a space(" ") in the same cell. Not a huge deal because the replace " " with "," can be done very quickly in the spreadsheet itself but it would be nice to work this into the code to improve reusability.
For a CSV file, use double-quotes around the cell content to preserve interior commas within, like this:
content1,content2,"content3,contains,commas",content4
Generally speaking, many libraries that output CSV just put all contents in quotes, like this:
"content1","content2","content3,contains,commas","content4"
As a side note, I'd strongly recommend using an existing library to create CSV files instead of reinventing the wheel. One such library is built into Python 2.6+.
As they say, "Good coders write. Great coders reuse."
import arcpy,collections,re,csv
arcpy.env.overwriteOutput = True
input = [# list of feature classes]
outfile= # path to output csv file
f=open(outfile,'wb')
csv_write=csv.writer(f)
csv_write.writerow(['Field','Feature Class'])
csv_write.writerow('')
mydict = collections.defaultdict(list)
for fc in input:
cmp=[]
lstflds=arcpy.ListFields(fc)
for fld in lstflds:
cmp.append(fld.name)
for item in cmp:
mydict[item].append(fc)
for keys, vals in mydict.items():
# remove these characters
char_removal = ["[","'","]"]
new_char = '[' + re.escape(''.join(char_removal)) + ']'
v=re.sub(new_char,'', str(vals))
csv_write.writerow([keys,""+v+""])
f.close()

Python: create dict from list and auto-gen/increment the keys (list is the actual key values)?

i've searched pretty hard and cant find a question that exactly pertains to what i want to..
I have a file called "words" that has about 1000 lines of random A-Z sorted words...
10th
1st
2nd
3rd
4th
5th
6th
7th
8th
9th
a
AAA
AAAS
Aarhus
Aaron
AAU
ABA
Ababa
aback
abacus
abalone
abandon
abase
abash
abate
abater
abbas
abbe
abbey
abbot
Abbott
abbreviate
abc
abdicate
abdomen
abdominal
abduct
Abe
abed
Abel
Abelian
I am trying to load this file into a dictionary, where using the word are the key values and the keys are actually auto-gen/auto-incremented for each word
e.g {0:10th, 1:1st, 2:2nd} ...etc..etc...
below is the code i've hobbled together so far, it seems to sort of works but its only showing me the last entry in the file as the only dict pair element
f3data = open('words')
mydict = {}
for line in f3data:
print line.strip()
cmyline = line.split()
key = +1
mydict [key] = cmyline
print mydict
key = +1
+1 is the same thing as 1. I assume you meant key += 1. I also can't see a reason why you'd split each line when there's only one item per line.
However, there's really no reason to do the looping yourself.
with open('words') as f3data:
mydict = dict(enumerate(line.strip() for line in f3data))
dict(enumerate(x.rstrip() for x in f3data))
But your error is key += 1.
f3data = open('words')
print f3data.readlines()
The use of zero-based numeric keys in a dict is very suspicious. Consider whether a simple list would suffice.
Here is an example using a list comprehension:
>>> mylist = [word.strip() for word in open('/usr/share/dict/words')]
>>> mylist[1]
'A'
>>> mylist[10]
"Aaron's"
>>> mylist[100]
"Addie's"
>>> mylist[1000]
"Armand's"
>>> mylist[10000]
"Loyd's"
I use str.strip() to remove whitespace and newlines, which are present in /usr/share/dict/words. This may not be necessary with your data.
However, if you really need a dictionary, Python's enumerate() built-in function is your friend here, and you can pass the output directly into the dict() function to create it:
>>> mydict = dict(enumerate(word.strip() for word in open('/usr/share/dict/words')))
>>> mydict[1]
'A'
>>> mydict[10]
"Aaron's"
>>> mydict[100]
"Addie's"
>>> mydict[1000]
"Armand's"
>>> mydict[10000]
"Loyd's"
With keys that dense, you don't want a dict, you want a list.
with open('words') as fp:
data = map(str.strip, fp.readlines())
But if you really can't live without a dict:
with open('words') as fp:
data = dict(enumerate(X.strip() for X in fp))
{index: x.strip() for index, x in enumerate(open('filename.txt'))}
This code uses a dictionary comprehension and the enumerate built-in, which takes an input sequence (in this case, the file object, which yields each line when iterated through) and returns an index along with the item. Then, a dictionary is built up with the index and text.
One question: why not just use a list if all of your keys are integers?
Finally, your original code should be
f3data = open('words')
mydict = {}
for index, line in enumerate(f3data):
cmyline = line.strip()
mydict[index] = cmyline
print mydict
Putting the words in a dict makes no sense. If you're using numbers as keys you should be using a list.
from __future__ import with_statement
with open('words.txt', 'r') as f:
lines = f.readlines()
words = {}
for n, line in enumerate(lines):
words[n] = line.strip()
print words

Categories

Resources