0

I am looking for a way to optimize the current code that I have:

        for result in results:
            if result != '':
                if isinstance(result, list):
                    for subresult in result:
                        if subresult != '':
                            worksheet.write(r, c, subresult)
                            c += 1
                else:
                    worksheet.write(r, c, result)
                    c += 1

I also use this in a particular case:

        for result in results:
            if isinstance(result, list):
                for subresult in result:
                    worksheet.write(r, c, subresult)
                    c += 1
            else:
                worksheet.write(r, c, result)
                c += 1

I have a list that in some instances contains only a single value, while in other instances it contains multiple values (i.e. another list).

Here is an example of what the list may contain:

results = ['', '', '', '390', '66', ['Name', 'SerialNumber', 'Model', 'Year'], 'SW_Version', ['HD_Loc', 'HD_Model', 'HD_FW', 'HD_SerialNumber', 'Man_Yr', 'Man_Mth'], '', '', '']

Ultimately I want to be able to output each value to its own column in excel. In some cases I only want to output the parts of the list that contain a value, which is performed by the first snippet of code I provided. In other cases I want to output all parts of the list, regardless of whether it has a value or not, which is performed by the second snippet of code I provided.

I have seen instances where a for loop and some action statement, lets say print, have been combined into a single line of python code, but I have been unable to get that syntax to work with the snippets that I have provided.

This code is currently working in the way I have implemented it, I am just looking for a way to shorten/optimize it as the program I have it inside of is starting to get fairly large and being able to shorten this would help me in shortening other parts of the program also.

Thanks in advance!

Edit: In both cases the order of which it is output does matter, and I would like to have it output in the order that it is currently in (just minus the '' in the one scenario).

Saltz3
  • 324
  • 1
  • 4
  • 15
  • so do you want to convert a list of lists to simply a list? – Jeremy Aug 03 '15 at 19:53
  • Effectively yes. When I perform the above code I get `['', '', '', '390', '66', 'Name', 'SerialNumber', 'Model', 'Year', 'SW_Version', 'HD_Loc', 'HD_Model', 'HD_FW', 'HD_SerialNumber', 'Man_Yr', 'Man_Mth', '', '', '']` and that is what I want output to my excel file (each being in their own cell.) – Saltz3 Aug 03 '15 at 20:09
  • look at this link and the links in the OP http://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python?rq=1 – Jeremy Aug 03 '15 at 20:11
  • Jeremy, I had tried that but I receive this: `['3', '9', '0', '6', '6', 'Name', 'SerialNumber', 'Model', 'Year', 'S', 'W', '_', 'V', 'e', 'r', 's', 'i', 'o', 'n', 'HD_Loc', 'HD_Model', 'HD_FW', 'HD_SerialNumber', 'Man_Yr', 'Man_Mth']` Looks like anything that was not in a list inside the list gets separated out by character, but anything that was in a list is fine. – Saltz3 Aug 03 '15 at 20:19
  • I posted a tentative solution. I will try and clean it up a bit – Jeremy Aug 03 '15 at 20:39

4 Answers4

1

You can do this neatly with recursion:

def worksheet_writer(results):
        if isinstance(results, list):
                for item in results: worksheet_writer(item)
        else:
                worksheet.write(r, c, results)
                c += 1

Edited to support strings.

jpcgt
  • 2,138
  • 2
  • 19
  • 34
  • jpcgt, I tried this and recieved" `Traceback (most recent call last): File "", line 11, in worksheet_writer(results) File "", line 3, in worksheet_writer for item in results: worksheet_writer(item)...(repeates for awhile)... File "", line 3, in worksheet_writer for item in results: worksheet_writer(item) RuntimeError: maximum recursion depth exceeded` – Saltz3 Aug 03 '15 at 20:15
  • 1
    This will cause a stack overflow on a string, because iterating over a string yields strings. – iobender Aug 03 '15 at 20:44
  • @RC_Crusher07: I just modified the answer to support string. Still, same recursion technique. – jpcgt Aug 03 '15 at 21:25
  • @jpcgt: This works for the second snippet of code I had added, but for the first piece where I want to exclude the blanks `''`, where would be the best place to add in `item != ''`? – Saltz3 Aug 04 '15 at 13:16
  • @RC_Crusher07: Instead of `else:` do `elif results != '':`. Not lines added! – jpcgt Aug 04 '15 at 15:44
  • @jpcgt: Thanks, that did it. But SuJaY posted closer to what I was looking for with the one liner that could do it, I have upvoted yours though. – Saltz3 Aug 04 '15 at 16:00
  • @RC_Crusher07: Appreciated. But you wanted better code, which can be either more readable, maintainable or faster. That one-liner is certainly not as readable, maintainable or faster. – jpcgt Aug 04 '15 at 19:37
  • @jpcgt: I am still fairly new to python. Is there an easy way I would be able to test the performance of your code versus the one a did choose to see if there is an advantage to one over the other? – Saltz3 Aug 04 '15 at 20:02
  • @RC_Crusher: One basic rule in software development is NEVER optimize for speed at the cost of readability and maintainability unless it's absolutely necessary. For measuring speed see http://stackoverflow.com/questions/582336/how-can-you-profile-a-python-script – jpcgt Aug 05 '15 at 20:41
1

Okay here's the solution I've got so far. It's a kinda messy list comprehension. I'll try and clean it up a bit.

results = ['', '', '', '390', '66', ['Name', 'SerialNumber', 'Model', 'Year'], 'SW_Version', ['HD_Loc', 'HD_Model', 'HD_FW', 'HD_SerialNumber', 'Man_Yr', 'Man_Mth'], '', '', '']
li = list(set([item if type(sublist) is list else sublist for sublist in results for item in sublist]))
print li

This gives an output of:

['SW_Version', 'Name', 'HD_FW', 'SerialNumber', 'HD_Model', 'HD_SerialNumber', '390', '66', 'Year', 'Model', 'Man_Yr', 'HD_Loc', 'Man_Mth']
Jeremy
  • 818
  • 6
  • 19
  • This does work, but it moves the values in the list out of order. Sorry I forgot to mention that order does matter, I will update my question. – Saltz3 Aug 04 '15 at 12:56
1

I hope this helps,

results = ['', '', '', '390', '66', ['Name', 'SerialNumber', 'Model', 'Year'], 'SW_Version', ['HD_Loc', 'HD_Model', 'HD_FW', 'HD_SerialNumber', 'Man_Yr', 'Man_Mth'], '', '', '']

flatList = [item for sublist in [[item] if not isinstance(item,list) else item for item in results] for item in sublist]

flatListWithoutBlanks = [item for item in [item for sublist in [[item] if not isinstance(item,list) else item for item in results] for item in sublist] if item != '' ]

best,

Sujay Narayanan
  • 487
  • 4
  • 11
  • Thanks, this does work for the second snippet of code I provided where I want to output the blanks, `''`, but is there a way to make it work for the first snippet where I want to exclude the blanks `''`? – Saltz3 Aug 04 '15 at 15:10
  • I have upvoted it, but does not currently show since I do not have enough reputation :(. Still a StackOverflow noob. – Saltz3 Aug 04 '15 at 15:39
  • No problem.. Have a nice day. – Sujay Narayanan Aug 04 '15 at 15:39
1

I posted it in a comment but not sure if it will be clear so ,

flatListWithoutBlanks = [item for item in [item for sublist in [[item] if not isinstance(item,list) else item for item in results] for item in sublist] if item != '' ]
Sujay Narayanan
  • 487
  • 4
  • 11