Determining the length of strings in a list

R

robin.siebler

I have a dictionary. Each key contains a list. I am using the
contents of the list to build a portion of a command line.

However, before I can build the command line, I have to make sure that
the command isn't too long. This means that I have to step through
each item in the list twice: once to check the length and once to build
the command. Is there an easier/better way to do this?

for key in dict:
tlen = 0
for item in dict[key]:
tlen = tlen + len(item)
if tlen > 200:
#break command portion into multiple portions ...
for key in dict:
for item in dict[key]:
#buld command
 
M

Michael Hoffman

I have a dictionary. Each key contains a list. I am using the
contents of the list to build a portion of a command line.

However, before I can build the command line, I have to make sure that
the command isn't too long. This means that I have to step through
each item in the list twice: once to check the length and once to build
the command. Is there an easier/better way to do this?

I'm not exactly sure what is done in "break command portion into
multiple portions," but you could always build the command and then
check the list.

Or you can get the length of all of the values this way:

sum(len(value) for value in cmdline_dict.itervalues())

I don't think it's a good idea to call your dict "dict" as it shadows a
built-in.
 
M

Michael Spencer

I have a dictionary. Each key contains a list. I am using the
contents of the list to build a portion of a command line.

However, before I can build the command line, I have to make sure that
the command isn't too long.

Depending on how you join the list items, you may just be able to use join
followed by stdlib textwrap to do this in one step (note I've wrapped this
example at width 20 rather than 200 to make the resulting list easier to read):
>>> source = ["some", "text", "fragments", "in", "a", "list"] * 10
>>> import textwrap
>>> textwrap.wrap(" ".join(source),20)
['some text fragments', 'in a list some text', 'fragments in a list', 'some
text fragments', 'in a list some text', 'fragments in a list', 'some text
fragments', 'in a list some text', 'fragments in a list', 'some text fragments',
'in a list some text', 'fragments in a list', 'some text fragments', 'in a list
some text', 'fragments in a list']

This works because the join separator is whitespace, which textwrap ignores. If
however, you need a non-whitespace separator, then textwrap can lead to ugly
results with a leading or trailing separator:
['some, fragments, of,', 'text, some,', 'fragments, of, text,', 'some,
fragments, of,', 'text, some,', 'fragments, of, text,', 'some, fragments, of,',
'text, some,', 'fragments, of, text,', 'some, fragments, of,', 'text, some,',
'fragments, of, text,', 'some, fragments, of,', 'text, some,', 'fragments, of,
text']

If you care about this, you may be able to tweak textwrap.TextWrapper to handle
this, or you could use your own function, like:


def iterjoin(iterable, separator = " ", width = 70):
"""joins an iterable of strings into strings with width <= maxlen
Not (yet) rejected for inclusion in itertools ;-)"""
accumulator = []
len_accumulator = 0
len_sep = len(separator)
for item in iterable:
item = item.expandtabs()
len_item = len(item)
trial_len = len_accumulator + len_sep + len_item
if trial_len > width:
yield separator.join(accumulator)
accumulator = [item]
len_accumulator = len_item
else:
# continue to build the command
accumulator.append(item)
len_accumulator = trial_len
if accumulator:
yield separator.join(accumulator)

['some, fragments', 'of, text, some', 'fragments, of, text', 'some, fragments,
of', 'text, some', 'fragments, of, text', 'some, fragments, of', 'text, some',
'fragments, of, text', 'some, fragments, of', 'text, some', 'fragments, of,
text', 'some, fragments, of', 'text, some', 'fragments, of, text']
Now you can simply iterate over each list in your dictionary:

for k in d:
for command in iterjoin(d[k], your_separator_here, width = 200)

HTH

Michael
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top