检查对象是否是字符串列表的列表?

时间:2014-02-12 09:37:20

标签: python functional-programming

什么是优雅方法来检查对象是否是字符串列表列表,没有嵌套循环?可能这里必须是构造结构化迭代的传统方法。

UPD

这样的事情:

l = [['a', 'b', 'c'], ['d', 1], 3, ['e', 2, 'f']]

def recurse(iterable, levels):
    results = []
    try:
        fn = levels[0]
    except IndexError:
        return
    for e in iterable:
        results.append(fn(e))
        try:
            results.extend(recurse(e, levels[1:]))
        except TypeError:
            pass
    return results

instance_of = lambda t: lambda e: isinstance(e, t)
print(recurse(l, [instance_of(list), instance_of(basestring)]))

UPD#2

我做了一些自制的函数式编程,现在它检查字符串列表的列表列表:

from collections import Iterable
from itertools import imap, chain


def compose(f, g):
    return lambda *a, **kw: f(g(*a, **kw))

def concat(iterable):
    return chain.from_iterable(iterable)

def mk_iter(o):
    if isinstance(o, Iterable):
        return o
    else:
        return [o]

def put_in(f, g):
    """To support spirit of the Olympics :)"""
    return lambda e: concat(
        [mk_iter(f(e)),
         concat(imap(compose(mk_iter, g), mk_iter(e)))]
    )


ckr = lambda t: lambda e: isinstance(e, t)

l = [[['a', 'b'], ['c']], [['d'], ['1']], [1]]

fns = [ckr(list), ckr(list),ckr(list), ckr(str)]
fns.reverse()

print(list(reduce(lambda x, y: put_in(y, x), fns)(l)))

4 个答案:

答案 0 :(得分:2)

lol = [["a", "b"], ["c"], ["d", "e"], [1]]

from itertools import chain
print isinstance(lol, list) and all(isinstance(items, list) \
        and all(isinstance(item, str) for item in items) for items in lol)

答案 1 :(得分:1)

>>> lls = [ ["he","li"],["be","b"],["c","n","o"],["f","ne","na"] ]
>>> isinstance(lls,list) and all([ all(isinstance(y,str) for y in x) and isinstance(x,list) for x in lls])
True
>>> not_lls = [ ["he","li"],["be",1]]
>>> isinstance(lls,list) and all([ all(isinstance(y,str) for y in x) and isinstance(x,list) for x in not_lls])
False
>>> not_also_lls = [ ["he","li"],{}]
>>> isinstance(lls,list) and all([ all(isinstance(y,str) for y in x) and isinstance(x,list) for x in not_also_lls])
False

答案 2 :(得分:1)

以更通用的方式:

def validate(x, types):
    if not isinstance(x, types[0]):
        raise ValueError('expected %s got %s for %r' % (types[0], type(x), x))
    if len(types) > 1:
        for y in x:
            validate(y, types[1:])

用法:

try:
    validate(
        [['a', 'b', 'c'], ['d', 1], 3, ['e', 2, 'f']],
        [list, list, str])
except ValueError as e:
    print e  # expected <type 'str'> got <type 'int'> for 1
try:
    validate(
        [['a', 'b', 'c'], ['d', 'X'], 3, ['e', 2, 'f']],
        [list, list, str])
except ValueError as e:
    print e # expected <type 'list'> got <type 'int'> for 3

try:
    validate(
        [['a', 'b', 'c'], ['d', 'X'], ['3'], ['e', '2', 'f']],
        [list, list, str])
except ValueError as e:
    print e
else:
    print 'ok' # ok

答案 3 :(得分:0)

平原直截了当:

def isListOfStrings(los):
  return isinstance(los, list) and all(isinstance(e, str) for e in los)

def isListOfListOfStrings(lolos):
  return isinstance(lolos, list) and all(isListOfStrings(los) for los in lolos)

print isListOfListOfStrings([["foo"]])

我不能在这推荐递归,因为外部的测试并不真正类似于内部的测试。如果递归的深度没有固定(如本例所示)并且每个级别的任务相似(这里不是这种情况),递归会更有用。