Sakyamooni
Sakyamooni

Reputation: 193

Mapping list to csv using loops and dictionary

im using Python and it seems that I have an issue with my for loop.

So here are the data sets that I am working with:

A) I have this csv file, that contains all the car data

enter image description here

B) I have also the Brand to Car (type) in csv that looks like below

enter image description here

What I need to build is to build another CSV that breaks down each line into its correct brand and car type. while making sure that it is accurate (for example there is Camry L and Camry LE - sometimes it pulls both).

This is the output that I am looking for:

enter image description here

So far here is my script:

temp_car_list = []
reader_type = csv.DictReader(type_library)

with open(file_name) as Output_file:
    reader = csv.DictReader(Output_file)
    for row in reader:
        Title = row ["Item Name"]
        print (Title)
        for brand in brand_library_iterate:
            if brand in Title:
                Brand_Name = brand
                print(Brand_Name)
        #Get Type Library List
        for Car_type in reader_type:
            Brand_String = str(Brand_Name)
            print(Brand_String)
            type_list = temp_car_list.append(Car_type[Brand_String])
        print(temp_car_list)
        for car_type in temp_car_list:
            if car_type in Title:
                car_type_output = car_type
                print (car_type_output)
        temp_car_list.clear()

Logic of the script:

1)Pull Title (e.g. Black Toyota Camry L)

2)Pull The brand of the car from a list

3)From output #2 - map into #B (the csv file in the picture)

Here is what I get (unfortunately):

enter image description here

What I have noticed to be the main issue:

1) for some reason the Brand_Name does not change in accordance to the second or subsequent rows. So it is stuck at Toyota.

2) The car_type_output pulls out both Camry L and Camry LE

Upvotes: 0

Views: 71

Answers (1)

stovfl
stovfl

Reputation: 15533

Question: Break down each line into its correct brand, color and car type.

A = """Item Name
Black Toyota Camry L
Honda Accord Navy
Grey Toyota Corolla
Black Nissan Murano
Silver Toyota Camry LE
"""

B = """Toyota,Nissan,Honda
Camry L,Murano,Accord
Corolla,Rogue,Civic
Avalon,Pathfinder,CR-V
Highlander,Maxima,HR-V
Prius,Altima,
Camry LE,,
"""

  1. The simplest approach by spliting the lines from file A.
    From file B only the first line with the brands are used to detect the out of order line:
    Honda Accord Navy.
import io


def simple_split_title():
    # with open(<name of your file B>) as fh:
    with io.StringIO(B) as fh:
        brands = fh.readline().rstrip().split(',')

    # with open(<name of your file A>) as fh:
    with io.StringIO(A) as fh:
        _ = next(fh)
        for line in fh:
            title = line.rstrip()
            item = title.split(' ')

            if item[0] in brands:
                _color, _brand, _type, _last = len(item) - 1, 0, 1, len(item) - 1
            else:
                _color, _brand, _type, _last = 0, 1, 2, len(item)

            result = {'title': title, 
                      'brand': item[_brand], 
                      'color': item[_color], 
                      'type': ' '.join(item[_type:_last])}
            print(result)
  1. The most expensive approach. This requires to loop the dict from file B twice per line from file A.
    To detect the out of order line: Honda Accord Navy, two string comparson required.
import io, csv


def looping_dict():
    # with open(<name of your file B>) as fh:
    with io.StringIO(B) as fh:
        car_type = [_dict for _dict in csv.DictReader(fh)]

    # with open(<name of your file A>) as fh:
    with io.StringIO(A) as fh:
        _ = next(fh)
        for line in fh:
            title = line.rstrip()
            result = {'title': title, 'brand': '', 'color': '', 'type': ''}

            # Get brand
            for brand in car_type[0].keys():
                if brand in title:
                    result['brand'] = brand
                    title = title.replace(brand + ' ', '')
                    break

            # Get type
            for _type in car_type:
                if title.endswith(_type[brand]) or title.startswith(_type[brand]):
                    result['type'] = _type[brand]
                    title = title.replace(_type[brand], '')
                    break

            # Get color
            result['color'] = title.strip()

            print(result)
  1. The mathematical approach, using theory of sets.
    The list of car_type is only looped once per line of file A.
    A extra condition to detect the out of order line: Honda Accord Navy, is not required.
    You get a match, if the set of title items are a superset of car_type[x].set.
import io, csv
from collections import namedtuple

def theory_of_sets():
    CarType = namedtuple('CarType', 'set brand type')
    car_type = []
    # with open(<name of your file B>) as fh:
    with io.StringIO(B) as fh:
        for _dict in csv.DictReader(fh):
            for brand, _type in _dict.items():
                _set = {brand} | set(_type.split(' '))
                car_type.append(CarType._make((_set, brand, _type)))

    # with open(<name of your file A>) as fh:
    with io.StringIO(A) as fh:
        _ = next(fh)

        for line in fh:
            title = line.rstrip()
            _title = title.split(' ')
            _items = set(_title)

            result = None

            for ct in car_type:
                if _items.issuperset(ct.set):
                    result = {'title': title, 
                              'brand': ct.brand, 
                              'color': (_items - ct.set).pop(), 
                              'type': ct.type}
                    break

            print(result)

Output: All three examples print the same output.

{'title': 'Black Toyota Camry L', 'brand': 'Toyota', 'color': 'Black', 'type': 'Camry L'}
{'title': 'Honda Accord Navy', 'brand': 'Honda', 'color': 'Navy', 'type': 'Accord'}
{'title': 'Grey Toyota Corolla', 'brand': 'Toyota', 'color': 'Grey', 'type': 'Corolla'}
{'title': 'Black Nissan Murano', 'brand': 'Nissan', 'color': 'Black', 'type': 'Murano'}
{'title': 'Silver Toyota Camry LE', 'brand': 'Toyota', 'color': 'Silver', 'type': 'Camry LE'}

Upvotes: 2

Related Questions