Converting certain index values in list to int - list

I have searched for a solution to this, but I have not been able to find one, weirdly.
I am opening a file with the following contents in it.
Alex,10,0,6,3,7,4
Bob, 6,3,7,2,1,8
I want to convert all the values in score_list from 1-4 index value to an integer. I have tried to do so with this following but it just doesn't work.
score_list = []
def opening_file():
counter = 0
with open('scores.txt', newline='') as infile:
reader = csv.reader(infile)
for row in reader:
score_list.append(row[0:5])
counter = 0
while counter != 5:
counter +=1
row[counter] = int(row[counter])
print (score_list)
opening_file()
but it doesn't work and just produces
[['Alex', '10', '0', '6', '3'], ['Bob', ' 6', '3', '7', '2']]
instead of [['Alex', 10, 0, 6, 3], ['Bob', 6, 3, 7, 2]]

You are converting the items within row which is just a throwaway variable. Also you don't need to that redundant works, you can simply unpack your row to name and scores parts and use a list comprehension in order to convert the digits to integer.
with open('scores.txt', newline='') as infile:
reader = csv.reader(infile)
for row in reader:
name, *scores = row
score_list.append([name] + [int(i) for i in scores])

Your while loop transforming the values in row happens too late. Each row's values have already been copied (by a slice operation) into a new list which has been appended to score_list. And you only run the loop on the last row anyway (assuming your indentation in the question is correct).
Try something like this:
with open('scores.txt', newline='') as infile:
reader = csv.reader(infile)
for row in reader:
for i in range(1,5):
row[i] = int(row[i])
score_list.append(row[0:5])
I'm using a for loop on a range, rather than a while loop, just because it's more convenient (a while loop version could work just fine, it just requires more lines). The key thing is to change row inside the loop on reader and before we slice the row to append to score_list.

First of all, the code converts items in the row array, but you print the score_list array. Second, as it alters the row variable outside the reader for loop, it only alters the last row. You could do something like this:
import csv
def opening_file():
with open('scores.txt', newline='') as infile:
return [[row[0]] + [int(x) for x in row[1:]] for row in csv.reader(infile)]
score_list = opening_file()
print(str(score_list))

Related

Convert dictionary into list based on the keys

I am trying to convert my dictionary into list, with the same order of keys and values and inserting the line after end of each key values.
For example, I have the following:
mydict = {'Ball' : ['red', 'green'], 'Bat':['white', 'black'], 'wickets': ['white']}
I am trying to make as follows:
reqlist = ['Ball','red', 'green','\n', 'Bat','white', 'black', '\n', 'wickets','white', \n']
This is the code, I have tried:
reqlist = []
for k,v in mydict.iteritems():
for val in v:
reqlist.append([k+val+'\n'])
But, I do not get the expected output.
Pleased to hear some suggestions.
Thanks a lot in advance.
You are appending the key each time you are appending a value. Just pull it out of the loop, along with the new line.
reqlist = []
for k,v in mydict.iteritems():
reqlist.append(k)
for val in v:
reqlist.append(val)
reqlist.append('\n')

Dictionary update overwrites duplicate keys

I have a table that has 6982 records that I am reading through to make a dictionary. I used a literal to create the dictionary
fld_zone_dict = dict()
fields = ['uniqueid', 'FLD_ZONE', 'FLD_ZONE_1']
...
for row in cursor:
uid = row[0]
old_zone_value = row[1]
new_zone_value = row[2]
fld_zone_dict[uid] = [old_zone_value, new_zone_value]
However, I noticed that using this method, if a uid has the same value as a previous uid (theoretically, there could be duplicate), the entry gets overwritten. So, if I had 2 entries I wanted to add: 'CA10376036': ['AE', 'X'] and 'CA10376036': ['V', 'D'], the first one gets overwritten and I only get 'CA10376036': ['V', 'D']. How can I add to my dictionary with out overwriting the duplicate keys so that I get something like this?
fld_zone_dict = {'CA10376036': ['AE', 'X'], 'CA9194089':['D', 'X'],'CA10376036': ['V', 'D']....}
Short answer: There is no way to have duplicate keys in a dictionary object in Python.
However, if you were to restructure your data and take that key and put it inside of a dictionary that is nested in a list, you could have duplicate IDs. EX:
[
{
"id": "CA10376036",
"data: ['AE', 'X']
},
{
"id": "CA10376036",
"data: ['V', 'D']
},
]
Doing this though will negate any benefits of lookup speed and ease.
edit: blhsing also has a good example of how to restructure data with a reduced initial lookup time, though you would still have to iterate through data to get the record you wanted.
Dicts are not allowed to have duplicate keys in Python. You can use the dict.setdefault method to convert existing keys to a list instead:
for row in cursor:
uid = row[0]
old_zone_value = row[1]
new_zone_value = row[2]
fld_zone_dict.setdefault(uid, []).append([old_zone_value, new_zone_value])
so that fld_zone_dict will become like:
{'CA10376036': [['AE', 'X'], ['V', 'D']], 'CA9194089': ['D', 'X'], ...}
but then other keys will not have a list of lists as values, so you probably should convert them all instead:
for k, v in fld_zone_dict.items():
fld_zone_dict[k] = [v]
for row in cursor:
uid = row[0]
old_zone_value = row[1]
new_zone_value = row[2]
fld_zone_dict[uid].append([old_zone_value, new_zone_value])
so that fld_zone_dict will become like:
{'CA10376036': [['AE', 'X'], ['V', 'D']], 'CA9194089': [['D', 'X']], ...}

For-loop error: list index out of range

So I am rather new to programming and just recently started with Classes and we are supposed to make a phonebook that can be loaded in seperate text files.
I however keep running into the problem in this section that when I get into the for-loop. It hits a brick wall on
if storage[2] == permaStorage[i].number:
And tells me "IndexError: list index out of range". I am almost certain it is due to permaStorage starts out empty, but even when I attempt to fill it with temporary instances of Phonebook it tells me it out of range. The main reason it is there is to check if a phone number already exists within the permaStorage.
Anyone got a good tip on how to solve this or work around it?
(Sorry if the text is badly written. Just joined this site and not sure on the style)
class Phonebook():
def __init__(self):
self.name = ''
self.number = ''
def Add(name1, number1):
y = Phonebook()
y.name = name1
y.number = number1
return y
def Main():
permaStorage = []
while True:
print " add name number\n lookup name\n alias name newname\n change name number\n save filename\n load filename\n quit\n"
choices = raw_input ("What would you like to do?: ")
storage = choices.split(" ")
if storage[0] == "add":
for i in range(0, len(permaStorage)+1):
if storage[2] == permaStorage[i].number:
print "This number already exists. No two people can have the same phonenumber!\n"
break
if i == len(permaStorage):
print "hej"
try:
tempbox = Add(storage[1], storage[2])
permaStorage.append(tempbox)
except:
raw_input ("Remember to write name and phonenumber! Press any key to continue \n")
I think problem is that permaStorage is empty list and then u try to:
for i in range(0, len(permaStorage)+1):
if storage[2] == permaStorage[i].number:
will cause an error because permaStorage has 0 items but u trying to get first (i=0, permaStorage[0]) item.
I think you should replace second if clause with first one:
for i in range(0, len(permaStorage)+1):
if i == len(permaStorage):
print "hej"
try:
tempbox = Add(storage[1], storage[2])
permaStorage.append(tempbox)
if storage[2] == permaStorage[i].number:
print "This number already exists. No two people can have the same phonenumber!\n"
break
So in this case if perStorage is blank you will append some value and next if clause will be ok.
Indexing starts at zero in python. Hence, a list of length 5 has the last element index as 4 starting from 0. Change range to range(0, len(permastorage))
You should iterate upto the last element of the list, not beyond.
Try -
for i in range(0, len(permaStorage)):
The list of numbers produced in range() is from the start, but not including the end, so range(3) == [0, 1, 2].
So if your list x has length 10, range(0, len(x)) will give you 0 through 9, which is the correct indices of the elements of your list.
Adding 1 to len(x) will produce the range 0 through 10, and when you try to access x[10], it will fail.

How to encode a list in python 2.7.8 ?

I try to find a duplicate row value in field named "KOD" and then insert those values into "list2" and then print it. The field contain values with numbers and charecters not in English language(right to left language).
I using this code:
import arcpy
fc = r"G:\desktop\Project\lyr\aaa.shp"
list1 = []
list2 = []
counter = print list2
with arcpy.da.UpdateCursor(fc, "KOD") as cursor:name
for row in cursor:
list1.append(row)
if list1.count(row) >= 2 :
list2.append(row)
counter = counter +1
print counter
print list2
this is the result:
>>>
[]
6
[[u'\u05d3/640'], [u'69/100/02/10'], [u'\u05d3/640'], [u'35/100/02/10'], [u'1/195/03/10'], [u'35/100/02/10']]
>>>
i get 6 duplicated values- it's true, but i get also a strange strings names.
How can i decode those strings?
I already asked it in https://gis.stackexchange.com/questions/228104/print-a-duplicate-field-list-values-using-arcpy , but the moderator decided that this question suitable to stackoverflow.

Find top 5 word lengths in a text

I'm trying to write a program that takes two functions:
count_word_lengths which takes the argument text, a string of text, and returns a default dictionary that records the count for each word length. An example call to this function:
top5_lengths which takes the same argument text and returns a list of the top 5 word lengths.
Note: that in the event that
two lengths have the same frequency, they should be sorted in descending order. Also, if there are fewer than 5 word lengths it should return a shorter list of the sorted word lengths.
Example calls to count_word_lengths:
count_word_lengths("one one was a racehorse two two was one too"):
defaultdict(<class 'int'>, {1: 1, 3: 8, 9: 1})
Example calls to top5_lengths:
top5_lengths("one one was a racehorse two two was one too")
[3, 9, 1]
top5_lengths("feather feather feather chicken feather")
[7]
top5_lengths("the swift green fox jumped over a cool cat")
[3, 5, 4, 6, 1]
My current code is this, and seems to output all these calls, however it is failing a hidden test. What type of input am I not considering? Is my code actually behaving correctly? If not, how could I fix this?
from collections import defaultdict
length_tally = defaultdict(int)
final_list = []
def count_word_lengths(text):
words = text.split(' ')
for word in words:
length_tally[len(word)] += 1
return length_tally
def top5_word_lengths(text):
frequencies = count_word_lengths(text)
list_of_frequencies = frequencies.items()
flipped = [(t[1], t[0]) for t in list_of_frequencies]
sorted_flipped = sorted(flipped)
reversed_sorted_flipped = sorted_flipped[::-1]
for item in reversed_sorted_flipped:
final_list.append(item[1])
return final_list
One thing to note is that you do not account for an empty string. That would cause count() to return null/undefined. Also you can use iteritems() during list comprehension to get the key and value from a dict like for k,v in dict.iteritems():
I'm not a Python guy, but I can see a few things that might cause issues.
You keep referring to top5_lengths, but your code has a function called top5_word_lengths.
You use a function called count_lengths that isn't defined anywhere.
Fix these and see what happens!
Edit:
This shouldn't impact your code, but it's not great practice for your functions to update variables outside their scope. You probably want to move the variable assignments at the top to functions where they're used.
Not really an answer, but an alternative way of tracking words instead of just lengths:
from collections import defaultdict
def count_words_by_length(text):
words = [(len(word),word) for word in text.split(" ")]
d = defaultdict(list)
for k, v in words:
d[k].append(v)
return d
def top_words(dict, how_many):
return [{"word_length": length, "num_words": len(words)} for length, words in dict.items()[-how_many:]]
Use as follows:
my_dict = count_words_by_length('hello sir this is a beautiful day right')
my_top_words = num_top_words_by_length(my_dict, 5)
print(my_top_words)
print(my_dict)
Output:
[{'word_length': 9, 'num_words': 1}]
defaultdict(<type 'list'>, {1: ['a'], 2: ['is'], 3: ['sir', 'day'], 4: ['this'], 5: ['hello', 'right'], 9: ['beautiful']})