3

Suppose I have a list of list of strings like this:

l=[['a','kl_hg', 'FOO'],['b', 'kl_c', 'po']]

Now I would like to use an if command as follows (in pseudo-code!):

if allElementsOf(l).isString():
#do something

From this question I learned how to check a single variable whether it is a string. For a single list I could therefore do:

dummyL = ['a','kl_hg', 'FOO']
if all(isinstance(s, basestring) for s in dummyL):
#do something

and for my actual list l I could then do:

if all(isinstance(el, basestring) for sl in l for el in sl):
#do something

Is that the way to do it or is there a faster solution since that takes some time for huge lists of lists?

Community
  • 1
  • 1
Cleb
  • 25,102
  • 20
  • 116
  • 151

4 Answers4

3

Your approach is right, any flatting list short cut seems slowest. A fastest way may be use itertools:

import itertools
l=[['a','kl_hg', 'FOO'],['b', 'kl_c', 'po']]
if all( isinstance(x, basestring) for x in  itertools.chain.from_iterable(l) ):
    ...
Community
  • 1
  • 1
dani herrera
  • 48,760
  • 8
  • 117
  • 177
  • 1
    Nice, that works fine and seems faster than my approach. I upvote it and might accept it later (just in case something even better shows up). Thanks! – Cleb Jul 14 '15 at 17:19
3

It's odd how anyone has told any() built-in function:

seq = [['a','kl_hg', 'FOO'], ['b', 'kl_c', 'po', 13]]

def all_string(_iterable):    
    return not any([not isinstance(n, basestring) for i in _iterable 
                        for n in i])

all_string(seq) # returns False

The advantage when using any() function is that it does not evaluate the whole sequence, it returns when the first True value is found - In contrast to all().

felipsmartins
  • 13,269
  • 4
  • 48
  • 56
  • Works fine as well! Thanks for the alternative solution, I upvote your answer as well. – Cleb Jul 15 '15 at 08:19
1

You probably want to use recursion to solve this in the general case, for any level of nesting. For example:

def all_strings(thing):
    if isinstance(thing, str):
        return True
    elif isinstance(thing, list):
        for subthing in thing:
            if not all_strings(subthing):
                return False
        return True
    else:
        return False

>>> print all_strings('foo')
True
>>> print all_strings(['foo'])
True
>>> print all_strings(['foo',['foo']])
True
>>> print all_strings(['foo',[1, 'foo']])
False
>>> 
Andru Luvisi
  • 24,367
  • 6
  • 53
  • 66
  • Don't remember why I did not upvote this one; just came back to this old question and your solution works perfectly fine. Upvoted it now. – Cleb Oct 31 '16 at 16:06
0

You can use this:

for x in l:
    for a in range(3):
        if type((x[a])) == str:
            print(x[a], ' is a string')
BattleDrum
  • 798
  • 7
  • 13