元组列表中元组的小写第一个元素

时间:2017-10-31 18:38:38

标签: python list tuples text-processing

我有一份文件清单,标有相应的类别:

>>> sum(all(np.linalg.norm(p - q) > 3
            for p, q in combinations(np.random.rand(10, 3) * 10, 2))
        for _ in range(1000))
20

给出了以下元组列表,其中元组的第一个元素是单词列表(句子的标记)。例如:

documents = [(list(corpus.words(fileid)), category)
              for category in corpus.categories()
              for fileid in corpus.fileids(category)]

我想应用一些文本处理技术,但我希望维护元组格式列表。

我知道如果我只有一个单词列表,那就可以了:

[([u'A', u'pilot', u'investigation', u'of', u'a', u'multidisciplinary', 
u'quality', u'of', u'life', u'intervention', u'for', u'men', u'with', 
u'biochemical', u'recurrence', u'of', u'prostate', u'cancer', u'.'], 
'cancer'), 
([u'A', u'Systematic', u'Review', u'of', u'the', u'Effectiveness', 
u'of', u'Medical', u'Cannabis', u'for', u'Psychiatric', u',', 
u'Movement', u'and', u'Neurodegenerative', u'Disorders', u'.'], 'hd')]

但在这种情况下,我想将.lower()应用于元组列表中每个元组的第一个元素(字符串列表),并在尝试各种选项之后:

[w.lower() for w in words]

我总是收到这个错误:

  

AttributeError:'list'对象没有属性'lower'

我还尝试在创建列表之前应用我需要的东西,但.categories()和.fileids()是语料库的属性,它们也返回相同的错误(它们也是列表)。

任何帮助都将深表感谢。

解决:

@Adam Smith的答案和@vasia都是对的:

[[x.lower() for x in element] for element in documents],
[(x.lower(), y) for x,y in documents], or
[x[0].lower() for x in documents]

@ Adam的答案保持了元组结构; @vasia从创建元组列表中做到了这一点:

[([s.lower() for s in item[0]], item[1]) for item in documents]

谢谢大家:)

4 个答案:

答案 0 :(得分:3)

因此您的数据结构为[([str], str)]。每个元组为(list of strings, string)的元组列表。在尝试从中提取数据之前,深入了解这意味着什么非常重要。

这意味着for item in documents会为您提供一个元组列表,其中item是每个元组。

这意味着item[0]是每个元组中的列表。

这意味着for item in documents: for s in item[0]:将遍历该列表中的每个字符串。我们来试试吧!

[s.lower() for item in documents for s in item[0]]

这应该从您的示例数据中提供:

[u'a', u'p', u'i', u'o', u'a', u'm', ...]

如果您尝试保留元组格式,则可以执行以下操作:

[([s.lower() for s in item[0]], item[1]) for item in documents]

# or perhaps more readably
[([s.lower() for s in lst], val) for lst, val in documents]

这两个陈述都给出了:

[([u'a', u'p', u'i', u'o', u'a', u'm', ...], 'cancer'), ... ]

答案 1 :(得分:2)

你很亲密。您正在寻找这样的结构:

[([s.lower() for s in ls], cat) for ls, cat in documents]

这基本上将这两者放在一起:

[[x.lower() for x in element] for element in documents],
[(x.lower(), y) for x,y in documents]

答案 2 :(得分:1)

试试这个:

documents = [([word.lower() for word in corpus.words(fileid)], category)
              for category in corpus.categories()
              for fileid in corpus.fileids(category)]

答案 3 :(得分:1)

通常,元组是不可变的。但是,由于每个元组的第一个元素是一个列表,该列表可变的,因此您可以修改其内容而不更改该列表的元组所有权:

documents = [(...what you originally posted...) ... etc. ...]

for d in documents:
    # to lowercase all strings in the list
    # trailing '[:]' is important, need to modify list in place using slice
    d[0][:] = [w.lower() for w in d[0]]

    # or to just lower-case the first element of the list (which is what you asked for)
    d[0][0] = d[0][0].lower()

您不能只在字符串上调用lower()并让它更新 - lower()会返回一个新字符串。因此,要将字符串修改为小写版本,您必须通过它进行分配。如果字符串本身是一个元组成员,则这是不可能的,但由于您正在修改的字符串位于元组的列表中,因此您可以修改列表内容而无需修改元组对列表的所有权。