2
def main():
    salesData= readData('icecream.txt')
    print(salesData)
    #printReport(salesData)


# Reads the tabular data
# @param filename name of the input file
# @return a dictionary whose keys are ice cream flavors and whose values are sales data.

def readData(filename):
    # Create an empty dictionary.
    salesData={}

    infile=open(filename, "r")

    # Read each record from the file. 
    for line in infile:
        fields=line.split(":")  # what is field datatype
        flavor=fields[0]
        salesData[flavor]=buildList(fields)
        #print("SalesData", salesData)
        #print()
        #print()
    infile.close()
    return salesData

# Builds a list of store sales contained in the fields split from a string.
# @param fields a list of strings comprising the record fields
# @return a list of floating-point values

def buildList(fields):
    storeSales= []
    for i in range (1, len(fields)):
        sales=float(fields[i])
        storeSales.append(sales)
        #print('StoreSales', storeSales)
        #print()
    return storeSales

# Prints a sales report.
def printReport(salesData):
    numStores=0

#print the dictionary first without the totals?
#call print report


main()

When I run the program in its current state, it will give me the following output:

{'chocolate': [10225.25, 9025.0, 9505.0], 'strawberry': [9285.15, 8276.1, 8705.0], 'cookie dough': [7901.25, 4267.0, 7056.5], 'rocky road': [6700.1, 5012.45, 6011.0], 'vanilla': [8580.0, 7201.25, 8900.0]}

However, I NEED it to look like this:

chocolate    10225.25   9025.0      9505.0      Total: 28755.25
vanilla      8580.0     7201.25     8900.0      Total: 24681.25
rocky road   6700.1     5012.45     6011.0      Total: 17723.55
strawberry   9285.15    8276.1      8705.0      Total: 26266.25
cookie dough 7901.25    4267.0      7056.5      Total: 19224.75
           **42691.75   33781.8     40177.5**

Clean, organized, tabbed, perfect alignment. I don't know how to pull the data from the dictionary in a clean manner. I have to, in addition, add the totals for chocolate, etc. and the 1st, 2nd and 3rd columns. Presentation is important. It's not merely a "how do I output the data" but, "how do I output the data with a clean presentation." I was thinking of using nested for loops, or maybe something with a for loop. But where that for loop goes, or how I use it to print out the dictionary data cleanly how I want it to look like is beyond me. I've looked at other questions asked, but nothing comes close to this level of tabulation, organization and printing specifics for data coming from a dictionary. I've also attempted the often cited "for key, val in X.items():" but that hasn't worked for me. I don't even know where to start with that function and its confusing beyond belief. Where would I put it? How would I name it? Where would I go from there? Not to mention I have columns to add, and rows to add. This is a very specific question. Thank you.

ice cream
  • 23
  • 1
  • 5
  • I have no idea what's going on there... – ice cream Nov 25 '16 at 22:15
  • peter's answer doesn't address the the column addition...also, your code was excellent and worked great, it just didn't add up the columns. I was thinking of (maybe you could help me here) initializing three columns (col1, col2 and col3) at 0, and then += them for values [0] [1] and [2] and then printing `print("\t\t", col1, "\t", col2, "\t", col3)` however it does not work: it does not print the sum of the columns. Just one of the flavors. – ice cream Nov 25 '16 at 23:35
  • Yes. I was getting the output I wanted from your suggestion and I ran it successfully without a hitch; however, it was missing only three numbers: `42691.75 33781.8 40177.5`. That is to say, I still don't know how to sum the [0] values from each key into one number that prints below the respective column (repeat for [1] values and [2] values). – ice cream Nov 25 '16 at 23:46
  • Alright @ice cream, my outstation is finished. Let me know if it works out for you. – Christian Dean Nov 26 '16 at 00:47

5 Answers5

3

You can use python's string formatting to create a regular appearance.

There's a nice website just to do with python formatting: https://pyformat.info

The format of the table row will look something like:

>>> row = '{flavour}\t{sales[0]}\t{sales[1]}\t{sales[2]}\tTotal: {total}'

Then you can fill in the fields:

>>> row.format(flavour='chocolate',
...            sales=[10225.25, 9025.0, 9505.0],
...            total=sum([10225.25, 9025.0, 9505.0]))
'chocolate    10225.25   9025.0      9505.0      Total: 28755.25'

To pull these fields out of the dictionary:

>>> for flavour, sales in salesData.items():
...     print(row.format(flavour=flavour,
...                      sales=sales,
...                      total=sum(sales)))
chocolate    10225.25   9025.0      9505.0      Total: 28755.25
vanilla      8580.0     7201.25     8900.0      Total: 24681.25
rocky road   6700.1     5012.45     6011.0      Total: 17723.55
strawberry   9285.15    8276.1      8705.0      Total: 26266.25
cookie dough 7901.25    4267.0      7056.5      Total: 19224.75
Peter Wood
  • 23,859
  • 5
  • 60
  • 99
  • Hey thanks Peter. Appreciate it. A couple questions, though: Where does the for loop go? Is it inside the `def main():` function after `salesData=readData('icecream.txt')`? Also, I want to avoid, if at all possible, me manually carrying in the data into the program. You see, the goal was to have information from a file called `icecream.txt` (that has dictionary information) outputted directly into an excel-like format. I should be able to replace `icecream.txt` with, say, `candy.txt` and have it outputted in the same format without having to carry over all the data manually into core porgram. – ice cream Nov 25 '16 at 22:31
  • `printReport` looks like a good place to put the loop. Also, to pass the filename for the data into your script, see [How can I pass a filename as a parameter into my module?](https://stackoverflow.com/questions/491085/how-can-i-pass-a-filename-as-a-parameter-into-my-module.), or better [sys.argv\[1\] meaning in script](https://stackoverflow.com/questions/4117530/sys-argv1-meaning-in-script) – Peter Wood Nov 25 '16 at 23:33
1

Python has an excellent mini-language specifically for string formatting. This is what should be used.

You know that you want your format to be

flavor sell1 sell2 sell3 Total: total sells

Which would equate to the following string format:

"{} \t {} \t {} \t {} \t Total: {}"

So now that you know your format, the next step is to apply this format to every key, value pair in your dictionary. Use a for loop to iterate over each key, value pair.

for key, value in dictionary.items():
    print("{} \t {} \t {} \t {} \t Total: {}".format(...))

The last thing left to do is to fill in the blanks. You know that the keys in your dict() are the flavors, so the first parameter to format() would be the key variable:

.format(key, ...)

Next you need the three values from your key's, values. We could index each value out of of value:

.format(key, value[0], value[1], value[2], ...)

Bu that's a bit verbose, and Python had a better method. We can simply "unpack" the list of values into the appropriate spots using the syntax *iterable.

.format(key, *value, ...)

And the last value left to fill in would be your total. You can make use of the builtin function sum() to add all the values in values together:

.format(key, *value, sum(value))

Now to print the sum of each column, we first need the value of each key in your dict(). This can be done using a simple list comprehension:

sales = [value for value in d.values()]

Next, we need to get the first value from each list in sales and add the value. This can be done using a list comprehension and the zip() builtin function:

totals = [round(sum(l), 1) for l in zip(*sales)]

The round function is used with floats to round them to a certain decimal place. You can change that number to your liking, but I chose one. The last thing left to do is to print the totals of each column. After a bit of experimentation, this should work just fine:

`print("\t\t {}\t {}\t {}".format(*totals))

So the final, finished solution would be:

sales  = [value for value in d.values()]
    totals = [round(sum(l), 1) for l in zip(*sales)]
    for key, value in salesData.items():
        print("{} \t {} \t {} \t {} \t Total: {}".format(key, *value, sum(value)))
    print("\t\t {}\t {}\t {}".format(*totals))
Christian Dean
  • 22,138
  • 7
  • 54
  • 87
  • Thank you! This worked for me. However, I'm missing one thing: **how to output the sum of the column beneath each respective column.** Any help would be appreciated. – ice cream Nov 25 '16 at 22:47
  • I get an error that says "d" in "d.values()" is not defined...why is that? thanks! – ice cream Nov 26 '16 at 05:40
1

Try the following:

def format_data(data):
    for item in data:
        print('{:15} {:15} {:15} {:15} {:10} Total:{:5}'.format(
            item, data[item][0], data[item][1], data[item][2], '',
            sum(data[item])))
    print('{:15} {:15} {:15} {:15}'.format('',
        sum(data[item][0] for item in data),
        sum(data[item][1] for item in data),
        sum(data[item][2] for item in data)))

Output:

>>> data = {'chocolate': [10225.25, 9025.0, 9505.0], 'strawberry': [9285.15, 8276.1, 8705.0], 'cookie dough': [7901.25, 4267.0, 7056.5], 'rocky road': [6700.1, 5012.45, 6011.0], 'vanilla': [8580.0, 7201.25, 8900.0]}

>>> format_data(data)
rocky road               6700.1         5012.45          6011.0            Total:17723.55
strawberry              9285.15          8276.1          8705.0            Total:26266.25
vanilla                  8580.0         7201.25          8900.0            Total:24681.25
cookie dough            7901.25          4267.0          7056.5            Total:19224.75
chocolate              10225.25          9025.0          9505.0            Total:28755.25
                       42691.75         33781.8         40177.5
ettanany
  • 19,038
  • 9
  • 47
  • 63
0
for key, value in salesData.items():
    print("{} \t {} \t {} \t {} \t Total: {}".format(key, *value, sum(value)))
print("\t", "{} \t {} \t {} \t {} \t".format('',
sum(salesData[value][0] for value in salesData),
sum(salesData[value][1] for value in salesData),
sum(salesData[value][2] for value in salesData)))

Enter inside the def main(): and you will get the desired output.

ice cream
  • 23
  • 1
  • 5
0

You could use the library outputformat to help displaying dictionaries.

pip install outputformat

Then try the following:


import outputformat as ouf

d = {'chocolate': [10225.25, 9025.0, 9505.0], 'strawberry': [9285.15, 8276.1, 8705.0], 'cookie dough': [7901.25, 4267.0, 7056.5], 'rocky road': [6700.1, 5012.45, 6011.0], 'vanilla': [8580.0, 7201.25, 8900.0]}

ouf.showdict(d, title="Ice cream flavours", style="box", precision=2)

This should give you the following result:

╭────────────────────╮
│ Ice cream flavours │
├────────────────────╯
├ chocolate...: 10225.25, 9025.00, 9505.00
├ strawberry..: 9285.15, 8276.10, 8705.00
├ cookie dough: 7901.25, 4267.00, 7056.50
├ rocky road..: 6700.10, 5012.45, 6011.00
╰ vanilla.....: 8580.00, 7201.25, 8900.00
Delestro
  • 541
  • 4
  • 7