python - Stopping a loop when "items run out" even if it doesn't reach the proper if clause -


i want write code takes list of items , concatenates them (separated commas) long strings, each string not longer predefined length. example, list:

colors = ['blue','pink','yellow'] 

and max len of 10 chars, output of code be:

long string 0: blue,pink

long string 1: yellow

i created following code (below), pitfall cases total length of concatenated items shorter of max len allowed, or creates 1 or more long strings , total len of concatenation of residual items in list shorter max len.

what i'm trying ask this: in following code, how "stop" loop when items run out , yet concatenation short "else" clause isn't reached?

many :)

import pyperclip   # theoretical bug: when single item longer max_length. never happen intended use of code.     raw_list = pyperclip.paste()  split_list = raw_list.split()  unique_items_list = list(set(split_list))                                       # notice set unordered collections, , original order not maintained. not crucial purpose of code way now, remembering. see more: http://stackoverflow.com/a/7961390/2594546   print "there %d items in list." % len(split_list) print "there %d unique items in list." % len(unique_items_list)   max_length = 10                                                               # salesforce's filters allow 1000 chars, didn't want hard code in rest of code, in case.   list_of_long_strs = [] short_list = []                                                                 # hold items max_length chars long str. total_len = 0 items_processed = []        # used sanity checking in unique_items_list:     if total_len + len(i) + 1 <= max_length:                                    # +1 length of comma         short_list.append(i)         total_len += len(i) + 1         items_processed.append(i)     elif total_len + len(i) <= max_length:                                      # if there's no place item+comma, means we're nearing end of max_length chars mark. maybe can fit item without unneeded comma.         short_list.append(i)         total_len += len(i)                                                     # should end loop here somehow?         items_processed.append(i)     else:         long_str = ",".join(short_list)         if long_str[-1] == ",":                                                 # appending long_str list of long strings, while making sure item can't end "," can affect salesforce filters.             list_of_long_strs.append(long_str[:-1])         else:             list_of_long_strs.append(long_str)         del short_list[:]                                                       # in order empty list.         total_len = 0  unique_items_proccessed = list(set(items_processed)) print "number of items concatenated:", len(unique_items_proccessed)    def sanity_check():     if len(unique_items_list) == len(unique_items_proccessed):         print "all items concatenated"     else:           # other option len(unique_items_list) > len(unique_items_proccessed)         print "the following items weren't concatenated:"         print ",".join(list(set(unique_items_list)-set(unique_items_proccessed)))   sanity_check()    print ",".join(short_list)         # when loop doesn't end way should since < max_length. need find better way handle   item in list_of_long_strs:     print "long string %d:" % list_of_long_strs.index(item)     print item     print 

at moment, don't i in else case, miss out items, , don't deal short_list if isn't filled last item in loop.

the simplest solution restart short_list i in :

short_list = [i] total_len = 0 

and check after for loop whether there left in short_list, , deal if so:

if short_list:     list_of_long_strs.append(",".join(short_list)) 

you can simplify if checking:

new_len = total_len + len(i) if new_len < max_length:     ... elif new_len == max_length:     ... else:     ... 

get rid of if/else block starting:

if long_str[-1] == ",":    

(",".join(...) means never happens)

and neaten last part of code using enumerate (and i'd switch str.format):

for index, item in enumerate(list_of_long_strs):     print "long string {0}:".format(index)     print item 

more broadly, here's i'd do:

def process(unique_items_list, max_length=10):     """process list comma-separated strings maximum length."""     output = []     working = []     item in unique_items_list:         new_len = sum(map(len, working)) + len(working) + len(item)                 # ^ items                  ^ commas       ^ new item?         if new_len <= max_length:             working.append(item)         else:             output.append(working)             working = [item]     output.append(working)     return [",".join(sublist) sublist in output if sublist]  def print_out(str_list):     """print out list of strings indices."""     index, item in enumerate(str_list):         print("long string {0}:".format(index))         print(item) 

demo:

>>> print_out(process(["ab", "cd", "ef", "gh", "ij", "kl", "mn"])) long string 0: ab,cd,ef long string 1: gh,ij,kl long string 2: mn 

Comments

Popular posts from this blog

windows - Single EXE to Install Python Standalone Executable for Easy Distribution -

c# - Access objects in UserControl from MainWindow in WPF -

javascript - How to name a jQuery function to make a browser's back button work? -