2

I have to make a function whose purpose is taking in parameter a list.

Such as this one :

['music', ' extension=mp3', 'reports/INFOB131', ' extension=doc,docx,pdf', ' name_contains=INFOB131', ' max_size=100000', 'reports/INFOB132', ' extension=doc,docx,pdf', ' name_contains=INFOB132', ' max_size=100000', 'games', ' name_contains=SC2,Wesnoth', 'pictures/Namur', ' extension=jpeg', ' min_size=5000000', ' name_contains=cercle', 'pictures/autres', ' extension=jpeg', ' min_size=5000000']

And return a list similar to this :

data_config = [{'music' : {'extension':'mp3'}}, {'reports/INFOB131': {'extension': ['doc', 'docx','pdf'], 'name_contains':'INFOB131', 'max_size':100000}}, {'reports/INFOB132': {'extension': ['doc', 'docx','pdf'], 'name_contains':'INFOB132', 'max_size':100000}}]

So I made that function :

def my_function(list_in_question, my_config_list =[], prev_list = []):
    """ """
    enumerated_list = list(enumerate(list_in_question))

    if not '=' in enumerated_list[0][1]:
        main_key = enumerated_list[0][1]# référencé avant assignement
        pre_dict = {main_key : {}}


        for i in enumerated_list[1:]:

            if '=' in i[1] :
                splitted = i[1].split('=')
                prev_list.append({splitted[0] : splitted[1]})

            elif not '=' in i[1] and i[1] != main_key:
                for j in prev_list:
                    pre_dict[main_key].update(j)

                my_config_list.append(pre_dict)

                return my_function(list_in_question[i[0]:])

            elif not '=' in i[1] and i[1] == main_key and main_key!= enumerated_list[0][1]:
                return my_config_list
    else:
        print("The format of the file containig the data in not adequate !")

But I don't understand why when I execute it this way :

new_lines = ['music', ' extension=mp3', '', 'reports/INFOB131', ' extension=doc,docx,pdf', ' name_contains=INFOB131', ' max_size=100000', '', 'reports/INFOB132', ' extension=doc,docx,pdf', ' name_contains=INFOB132', ' max_size=100000', '', 'games', ' name_contains=SC2,Wesnoth', '', 'pictures/Namur', ' extension=jpeg', ' min_size=5000000', ' name_contains=cercle', '', 'pictures/autres', ' extension=jpeg', ' min_size=5000000']

my_function(new_lines)

I end up with this output...

None

I would be very grateful if someone could help me,

Thank you !

PS : If anyone have an idea of how I could do without loop and do it in a recursive way, it would be awesome !

Everyone... Thank you !!! You really hepled me, all your answers are awesome, I have some issues to understand some parts so I'll be annoying just a little longer with some questions of you code. Anyway, thank you for the time you took to help me, you were all more than great help !!!

Manoa
  • 37
  • 6

4 Answers4

1

Try the following code;

def foo(my_list):
    # Create an iterator
    list_iter = iter(my_list)
    # zip the iterator with itself
    key_val_tuple = zip(list_iter, list_iter) # This will group two items in the list at a time
    output_list = []
    for i in key_val_tuple:
        value_dict = {}
        value = i[1].split('=')
        value_dict[value[0]] = value[1].split(",") if len(value[1].split(","))>1 else value[1]
        element_dict = {}
        element_dict[i[0]] = value_dict
        output_list.append(element_dict)
    return output_list

input_list = ['music', ' extension=mp3', 'reports/INFOB131', ' extension=doc,docx,pdf', ' name_contains=INFOB131', ' max_size=100000', 'reports/INFOB132', ' extension=doc,docx,pdf', ' name_contains=INFOB132', ' max_size=100000', 'games', ' name_contains=SC2,Wesnoth', 'pictures/Namur', ' extension=jpeg', ' min_size=5000000', ' name_contains=cercle', 'pictures/autres', ' extension=jpeg', ' min_size=5000000']

# Call the function foo
output = foo(input_list)
print(output) # python3

Got the following output

[{'music': {' extension': 'mp3'}}, {'reports/INFOB131': {' extension': ['doc', 'docx', 'pdf']}}, {' name_contains=INFOB131': {' max_size': '100000'}}, {'reports/INFOB132': {' extension': ['doc', 'docx', 'pdf']}}, {' name_contains=INFOB132': {' max_size': '100000'}}, {'games': {' name_contains': ['SC2', 'Wesnoth']}}, {'pictures/Namur': {' extension': 'jpeg'}}, {' min_size=5000000': {' name_contains': 'cercle'}}, {'pictures/autres': {' extension': 'jpeg'}}]

  • zip(list_iter, list_iter) : This will group two items in the list at a time.

    output : [('music', ' extension=mp3'), ('reports/INFOB131', ' extension=doc,docx,pdf'), ...]

Reference:

aprasanth
  • 1,079
  • 7
  • 20
  • Thank you so much ! It worked perfectly !!! Just a question, could you explain me the use of the zip() and iter() ? – Manoa Dec 05 '17 at 14:36
  • Please see the updated answer with proper comments and reference links. Let me know if you have any doubts still.. – aprasanth Dec 06 '17 at 06:04
1

You need to traverse the list one time. The pattern is this:

  1. Start an empty list (let's call it new_list)
  2. You find an element in the original list (original_list).
  3. If it does not contain '=', you create a new dictionary in the new_list
  4. If it contains the '=' sign, split the element into k and v (before and after the '='), and in the last entry in the new_list, for the only key, you add a key-value pair

    def parse_list(original_list):
        new_list=[]
    
        for element in original_list:
            if not '=' in element:
                new_list.append({element:{}})
            else:
                k,w=element.split('=')
                new_list[-1][new_list[-1].keys()[0]][k]=w
        return new_list
    
    new_lines = ['music', ' extension=mp3', '', 'reports/INFOB131', ' extension=doc,docx,pdf', ' name_contains=INFOB131', ' max_size=100000', '', 'reports/INFOB132', ' extension=doc,docx,pdf', ' name_contains=INFOB132', ' max_size=100000', '', 'games', ' name_contains=SC2,Wesnoth', '', 'pictures/Namur', ' extension=jpeg', ' min_size=5000000', ' name_contains=cercle', '', 'pictures/autres', ' extension=jpeg', ' min_size=5000000']
    
    parse_list(new_lines)
    

Now I should explain the line before the return statement:

  • new_list[-1] is the dictionary corresponding to the last entry without an equal sign that was found in the original_list. After the first pass through the loop,

    new_list=[{'music': {}}]

  • during the second pass

    new_list[-1]={'music': {}}

    new_list[-1].keys()=['music']

    new_list[-1].keys()[0]='music'

    new_list[-1][new_list[-1].keys()[0]]={}

  • now you just update this dictionary with the parsed k,w pair

Andrei
  • 471
  • 6
  • 10
  • thank you for your help, if you could just help me to understand this line : new_list[-1][new_list[-1].keys()[0]][k]=w , why [-1] and what does .keys() do ? – Manoa Dec 05 '17 at 14:59
  • [-1] is the index of the last element in a list. somelist[-1] the same as somelist[len(somelist)-1]. The keys() function return the keys from the dictionary. {'extension': ['doc', 'docx','pdf'], 'name_contains':'INFOB131', 'max_size':100000}.keys() should return ['max_size', 'name_contains', 'extension']. I know that you main dictionaries contain only one key word (for example 'music') so I grabbed the first (and only) element in that list, so I can access the value (the dictionary with all other key-value pairs) – Andrei Dec 05 '17 at 16:35
1

Yet another try with only lists and dicts:

def make(lst):
    data_config=[]
    for st in lst:
        if '=' not in st:            # new entry
            dd = dict()
            dds = dd[st] = dict()
            data_config.append(dd)            
        else:                        # fill entry
            k,v = st.split('=')
            if ',' in v:
                v = v.split(',')
            dds[k] = v          
    return data_config  

For :

In [564]: make(l)
Out[564]: 
[{'music': {' extension': 'mp3'}},
 {'reports/INFOB131': {' extension': ['doc', 'docx', 'pdf'],
   ' max_size': '100000',
   ' name_contains': 'INFOB131'}},
 {'reports/INFOB132': {' extension': ['doc', 'docx', 'pdf'],
   ' max_size': '100000',
   ' name_contains': 'INFOB132'}},
 {'games': {' name_contains': ['SC2', 'Wesnoth']}},
 {'pictures/Namur': {' extension': 'jpeg',
   ' min_size': '5000000',
   ' name_contains': 'cercle'}},
 {'pictures/autres': {' extension': 'jpeg', ' min_size': '5000000'}}]
B. M.
  • 18,243
  • 2
  • 35
  • 54
1

One more way of doing it:

import re

def my_function(list_in_question, my_config_list=[], prev_list=[]):
    """ """
    result = {}
    main_key = ''

    for element in list_in_question:
        if element == '':
            main_key = ''
        if re.search('=', element):
            key, value = element.split('=')
            print "key, value = ", key, value
            if re.search(',', value):
                value_list = value.split(',')
                print "value list =", value_list
                result[main_key][key] = value_list
            else:
                result[main_key][key] = value

        else:
            main_key = element
            result[main_key] = {}

    return (result)

new_lines = ['music', ' extension=mp3', '', 'reports/INFOB131', ' extension=doc,docx,pdf', ' name_contains=INFOB131',
             ' max_size=100000', '', 'reports/INFOB132', ' extension=doc,docx,pdf', ' name_contains=INFOB132',
             ' max_size=100000', '', 'games', ' name_contains=SC2,Wesnoth', '', 'pictures/Namur', ' extension=jpeg',
             ' min_size=5000000', ' name_contains=cercle', '', 'pictures/autres', ' extension=jpeg',
             ' min_size=5000000']

print (my_function(new_lines))
eiram_mahera
  • 950
  • 9
  • 25
  • Thank you for your help, the code works the only issue I encountered is that I get the code in this order : – Manoa Dec 05 '17 at 15:26
  • {'games': {' name_contains': ['SC2', 'Wesnoth']}, 'music': {' extension': 'mp3'}, 'pictures/Namur': {' extension': 'jpeg', ' min_size': '5000000', ' name_contains': 'cercle'}, 'pictures/autres': {' extension': 'jpeg', ' min_size': '5000000'}, 'reports/INFOB131': {' extension': ['doc', 'docx', 'pdf'], ' max_size': '100000', ' name_contains': 'INFOB131'}, 'reports/INFOB132': {' extension': ['doc', 'docx', 'pdf'], ' max_size': '100000', ' name_contains': 'INFOB132'}} – Manoa Dec 05 '17 at 15:27