Applied Programming/Dictionaries and Sets/Python3

regex_dictionaries.pyEdit

This is the regex way of using dictionaries.

"""This program demonstrates file, list, and dictionary processing.

It creates a temporary file, adds data to the file, and reads the file
into a list of dictionaries. It then provides a menu of options for displaying 
and searching the file data.

It will not run if the file already exists.

Input:
    None

Output:
    A temporary file and file contents.

References:
    https://www.tutorialspoint.com/python/python_tuples.htm

"""

import os
import re
import sys

def create_file(filename):
    """Creates filename and adds temperature data to the file.

    Args:
        filename (string): Filename to create.

    Returns:
        None

    """
    with open(filename, 'w') as file:
        file.write('"C","F"\n')
        for c in range(0, 101, 10):
            f = c * 9 / 5 + 32
            file.write('"%.1f","%.1f"\n' % (c, f))


def read_file(filename):
    """Reads filename and returns a list of temperature tuples.

    Args:
        filename (string): Filename to open and read.

    Returns:
        A list of temperature tuples.
        
    Raises:
        ValueError: Invalid header format.
        ValueError: Invalid record format.
        ValueError: No data found.

    """
    with open(filename, 'r') as file:
        line = file.readline()
        if line.strip() != '"C","F"':
            raise ValueError("Invalid header format found in %s: %s" % 
                (filename, line))
            
        temperatures = []
        fields = ['C', 'F']
        for line in file:
            if 'C' in line:
                continue
            record = re.findall('"(.*?)"', line)
            if len(record) != len(fields):
                raise ValueError("Invalid record format found in %s: %s" % 
                    (filename, line))
                
            temperature = {}
            for i in range(len(fields)):
                temperature[fields[i]] = float(record[i])
            temperatures.append(temperature)
            
    if len(temperatures) == 0:
        raise ValueError("No data found in %s" % filename)
    return temperatures


def delete_file(filename):
    """Deletes filename.

    Args:
        filename (string): Filename to delete.

    Returns:
        None

    """
    os.remove(filename)


def get_choice():
    """Displays menu and gets choice.

    Args:
        None

    Returns:
        choice (int) or None

    """
    while True:
        try:
            print("Select from the following options or press <Enter> to quit:")
            print("1. Display table sorted by Celsius temperature.")
            print("2. Display table sorted by Fahrenheit temperature.")
            print("3. Search for Celsius temperature.")
            print("4. Search for Fahrenheit temperature.")
            choice = input()
            choice = int(choice)
            if 1 <= choice <= 4:
                print()
                return choice
            print("%s is not a valid choice.\n" % choice)
        except ValueError:
            if choice == "":
                return None
            print("%s is not a valid choice.\n" % choice)


def display_temperatures(temperatures, scale):
    """Displays temperatures sorted in scale order.
    
    Args:
        temperatures (list of Celsius, Fahrenheit tuples)
        scale (string): "Celsius" or "Fahrenheit"

    Returns:
        None

    """
    if scale == "Celsius":
        data = sorted(temperatures, key=lambda record: record['C'])
        fields = ['C', 'F']
    elif scale == "Fahrenheit":
        data = sorted(temperatures, key=lambda record: record['F'])
        fields = ['F', 'C']
    else:
        raise ValueError("scale must be Celsius or Fahrenheit")
    print("%s\t%s" % (fields[0], fields[1]))
    for record in data:
        print("%s\t%s" % (record[fields[0]], record[fields[1]]))
    print()


def get_temperature(scale):
    """Gets Fahrenheit or Celsius temperature.
    
    Args:
        scale (string): "Celsius" or "Fahrenheit"

    Returns:
        temperature (float) or None

    """
    assert scale == "Celsius" or scale == "Fahrenheit"
    while True:
        try:
            print("Enter %s temperature:" % scale)
            temperature = input()
            temperature = float(temperature)
            print()
            return temperature
        except ValueError:
            print("%s is not a valid %s temperature\n" %
                (temperature, scale))
            return None


def search_temperatures(temperatures, scale):
    """Search temperatures for a scale temperature and display the nearest match.
    
    Args:
        temperatures (list of Celsius, Fahrenheit tuples)
        scale (string): "Celsius" or "Fahrenheit"

    Returns:
        None

    Raises:
        ValueError: If temperatures list is empty
        ValueError: If scale is invalid
        
    """
    if len(temperatures) <= 0:
        raise ValueError("temperatures list is empty")
    
    temperature = get_temperature(scale)
    if temperature == None:
        return

    if scale == "Celsius":
        search_element = 'C'
        display_element = 'F'
        other_scale = "Fahrenheit"
    elif scale == "Fahrenheit":
        search_element = 'F'
        display_element = 'C'
        other_scale = "Celsius"
    else:
        raise ValueError("scale must be Celsius or Fahrenheit")
        
    data = sorted(temperatures, key=lambda record: record[search_element])
    last = data[0]
    for record in data:
        if temperature < record[search_element]:
            break
        last = record

    if temperature < last[search_element]:
        print("%.1f° %s is less than %.1f° %s\n" % 
            (temperature, scale, last[display_element], other_scale))
    elif temperature == last[search_element]:
        print("%.1f° %s is %.1f° %s\n" % 
            (temperature, scale, last[display_element], other_scale))
    elif temperature > record[search_element]:
        print("%.1f° %s is greater than %.1f° %s\n" % 
            (temperature, scale, last[display_element], other_scale))
    else:
        print("%.1f° %s is between %.1f° %s and %.1f° %s\n" %
            (temperature, scale, 
            last[display_element], other_scale,
            record[display_element], other_scale))
    

def main():
    """Runs the main program logic."""

    try:
        filename = "~temperatures.txt"

        if os.path.isfile(filename):
            print("File '%s' already exists." % filename)
            exit(1)

        create_file(filename)
        temperatures = read_file(filename)
        delete_file(filename)
        
        while True:
            choice = get_choice()
            if choice == None:
                break
            elif choice == 1:
                display_temperatures(temperatures, "Celsius")
            elif choice == 2:
                display_temperatures(temperatures, "Fahrenheit")
            elif choice == 3:
                search_temperatures(temperatures, "Celsius")
            elif choice == 4:
                search_temperatures(temperatures, "Fahrenheit")
            else:
                raise ValueError("Invalid option selected")
    except:
        print("Unexpected error.")
        print("Error:", sys.exc_info()[1])
        print("File: ", sys.exc_info()[2].tb_frame.f_code.co_filename) 
        print("Line: ", sys.exc_info()[2].tb_lineno)


main()

csv_dictionaries.pyEdit

"""This program demonstrates file, list, and dictionary processing.

It creates a temporary file, adds data to the file, and reads the file
into a list of dictionaries. It then provides a menu of options for displaying 
and searching the file data.

It will not run if the file already exists.

Input:
    None

Output:
    A temporary file and file contents.

References:
    https://www.tutorialspoint.com/python/python_tuples.htm

"""

import os
import csv
import sys


def create_file(filename):
    """Creates filename and adds temperature data to the file.

    Args:
        filename (string): Filename to create.

    Returns:
        None

    """
    with open(filename, 'w') as file:
        file.write('"C","F"\n')
        for c in range(0, 101, 10):
            f = c * 9 / 5 + 32
            file.write('"%.1f","%.1f"\n' % (c, f))


def read_file(filename):
    """Reads filename and returns a list of temperature tuples.

    Args:
        filename (string): Filename to open and read.

    Returns:
        A list of temperature tuples.
        
    Raises:
        ValueError: Invalid header format.
        ValueError: Invalid record format.
        ValueError: No data found.

    """
    with open(filename, 'r') as file:
        line = file.readline()
        if line.strip() != '"C","F"':
            raise ValueError("Invalid header format found in %s: %s" % 
                (filename, line))
        temperatures = []    
        fields = ['C', 'F']
        for line in file:
            if 'C' in line:
                continue
            reader = csv.reader(file)
            array = list(reader)
            if len(fields) != 2:
              raise ValueError("Invalid record format found in %s: %s" % 
                (filename, line))
                
        temperature = {}
        for i in range(len(fields)):
              temperature[fields[i]] = float(array[i][i])
        temperatures.append(temperature)
            
    if len(temperature) == 0:
        raise ValueError("No data found in %s" % filename)
    return temperatures


def delete_file(filename):
    """Deletes filename.

    Args:
        filename (string): Filename to delete.

    Returns:
        None

    """
    os.remove(filename)


def get_choice():
    """Displays menu and gets choice.

    Args:
        None

    Returns:
        choice (int) or None

    """
    while True:
        try:
            print("Select from the following options or press <Enter> to quit:")
            print("1. Display table sorted by Celsius temperature.")
            print("2. Display table sorted by Fahrenheit temperature.")
            print("3. Search for Celsius temperature.")
            print("4. Search for Fahrenheit temperature.")
            choice = input()
            choice = int(choice)
            if 1 <= choice <= 4:
                print()
                return choice
            print("%s is not a valid choice.\n" % choice)
        except ValueError:
            if choice == "":
                return None
            print("%s is not a valid choice.\n" % choice)


def display_temperatures(temperatures, scale):
    """Displays temperatures sorted in scale order.
    
    Args:
        temperatures (list of Celsius, Fahrenheit tuples)
        scale (string): "Celsius" or "Fahrenheit"

    Returns:
        None

    """
    if scale == "Celsius":
        data = sorted(temperatures, key=lambda record: record['C'])
        fields = ['C', 'F']
    elif scale == "Fahrenheit":
        data = sorted(temperatures, key=lambda record: record['F'])
        fields = ['F', 'C']
    else:
        raise ValueError("scale must be Celsius or Fahrenheit")
    print("%s\t%s" % (fields[0], fields[1]))
    for record in data:
        print("%s\t%s" % (record[fields[0]], record[fields[1]]))
    print()


def get_temperature(scale):
    """Gets Fahrenheit or Celsius temperature.
    
    Args:
        scale (string): "Celsius" or "Fahrenheit"

    Returns:
        temperature (float) or None

    """
    assert scale == "Celsius" or scale == "Fahrenheit"
    while True:
        try:
            print("Enter %s temperature:" % scale)
            temperature = input()
            temperature = float(temperature)
            print()
            return temperature
        except ValueError:
            print("%s is not a valid %s temperature\n" %
                (temperature, scale))
            return None


def search_temperatures(temperatures, scale):
    """Search temperatures for a scale temperature and display the nearest match.
    
    Args:
        temperatures (list of Celsius, Fahrenheit tuples)
        scale (string): "Celsius" or "Fahrenheit"

    Returns:
        None

    Raises:
        ValueError: If temperatures list is empty
        ValueError: If scale is invalid
        
    """
    if len(temperatures) <= 0:
        raise ValueError("temperatures list is empty")
    
    temperature = get_temperature(scale)
    if temperature == None:
        return

    if scale == "Celsius":
        search_element = 'C'
        display_element = 'F'
        other_scale = "Fahrenheit"
    elif scale == "Fahrenheit":
        search_element = 'F'
        display_element = 'C'
        other_scale = "Celsius"
    else:
        raise ValueError("scale must be Celsius or Fahrenheit")
        
    data = sorted(temperatures, key=lambda record: record[search_element])
    last = data[0]
    for record in data:
        if temperature < record[search_element]:
            break
        last = record

    if temperature < last[search_element]:
        print("%.1f° %s is less than %.1f° %s\n" % 
            (temperature, scale, last[display_element], other_scale))
    elif temperature == last[search_element]:
        print("%.1f° %s is %.1f° %s\n" % 
            (temperature, scale, last[display_element], other_scale))
    elif temperature > record[search_element]:
        print("%.1f° %s is greater than %.1f° %s\n" % 
            (temperature, scale, last[display_element], other_scale))
    else:
        print("%.1f° %s is between %.1f° %s and %.1f° %s\n" %
            (temperature, scale, 
            last[display_element], other_scale,
            record[display_element], other_scale))
    

def main():
    """Runs the main program logic.""" 
    try:
        
        filename = "~temperatures.txt"
        
        if os.path.isfile(filename):
            print("File '%s' already exists." % filename)
            os.remove(filename)  
            
        create_file(filename)
        temperatures = read_file(filename)
        delete_file(filename)
        
        while True:
            choice = get_choice()
            if choice == None:
                break
            elif choice == 1:
                display_temperatures(temperatures, "Celsius")
            elif choice == 2:
                display_temperatures(temperatures, "Fahrenheit")
            elif choice == 3:
                search_temperatures(temperatures, "Celsius")
            elif choice == 4:
                search_temperatures(temperatures, "Fahrenheit")
            else:
                raise ValueError("Invalid option selected")
    except:
        os.remove(filename)
        print("Unexpected error.")
        print("Error:", sys.exc_info()[1])
        print("File: ", sys.exc_info()[2].tb_frame.f_code.co_filename) 
        print("Line: ", sys.exc_info()[2].tb_lineno)


main()

Try ItEdit

Copy and paste the code above into one of the following free online development environments or use your own Python3 compiler / interpreter / IDE.

See AlsoEdit