列表理解:优雅地剥离和删除列表中的空元素
List Comprehension: Elegantly strip and remove empty elements in list
我正在使用 Scrapy 库。我经常收到带有“\t”和“\n”的列表。
我正在尝试使用列表理解来剥离和删除生成的空元素,但最终仍然是空元素。
有人可以解释一下解释器是如何处理代码的吗?它似乎正在检查空元素,然后剥离元素并将元素重新插入列表中。
提前致谢!
# input
char_list = ['', ' a','b', '\t']
print char_list
char_list = [x.strip() for x in char_list if x!='']
print char_list
# output
['', ' a', 'b', '\t']
['a', 'b', '']
#DESIRED output
['', ' a', 'b', '\t']
['a', 'b']
char_list = [x.strip() for x in char_list if x.strip()]
你想要的是删除无用的字符串。 x!="" 无法删除 "\t".
通常在这种情况下,我会将其更改为 2 个步骤...在第一步中,我会进行可能代价高昂的处理。在第二步中,我进行过滤。第一步可以使用生成器表达式来避免不必要的列表:
char_list_stripped = (x.strip() for x in char_list)
char_list = [x for x in char_list_stripped if x]
在这种情况下,它使您免于调用 x.strip
的次数是您实际需要的次数的两倍(如果您将其全部打包到一个推导式中)。这可能不会 巨大 节省(您可能不会注意到速度差异)。但在更一般的情况下,它可能会产生重大差异,具体取决于处理实际需要多少工作。
两次调用 strip() 的双重理解将比单一理解更有效
char_list = [ x for x in [ x.strip() for x in char_list ] if x ]
>>> char_list = ['', ' a','b', '\t']
>>> filter(None, map(str.strip, char_list))
['a', 'b']
在蜘蛛中硬编码这些东西不是一个好习惯。查看 Scrapy 的 built-in Item Loader 和 input/output 处理器。
在您的 REPL 中尝试以下操作:
from scrapy.contrib.loader.processor import MapCompose
def compact(s):
""" returns None if string is empty, otherwise string itself """
return s if s else None
char_list = ['', ' a','b', '\t']
MapCompose(unicode.strip, compact)(char_list)
=> ['a', 'b']
MapCompose 按顺序对每个项目应用给定的函数,每个函数将一个项目作为参数,从以后的处理中排除 None。
在您的 items.py:
中使用此方法的最简单方法
# -*- coding: utf-8 -*-
import scrapy
from scrapy.contrib.loader.processor import MapCompose
def compact(s):
return s if s else None
class MyItem(scrapy.Item):
my_field = scrapy.Field(
input_processor=MapCompose(unicode.strip, compact)
)
并且在您的蜘蛛 parse_my_items 回调中:
from scrapy.contrib.loader import ItemLoader
from myproject.items import MyItem
il = ItemLoader(item=MyItem())
il.add_value('my_field', char_list)
my_item = il.load_item()
yield my_item
#=> {'my_field': [u'a', u'b']}
希望对您有所帮助!
我正在使用 Scrapy 库。我经常收到带有“\t”和“\n”的列表。
我正在尝试使用列表理解来剥离和删除生成的空元素,但最终仍然是空元素。
有人可以解释一下解释器是如何处理代码的吗?它似乎正在检查空元素,然后剥离元素并将元素重新插入列表中。
提前致谢!
# input
char_list = ['', ' a','b', '\t']
print char_list
char_list = [x.strip() for x in char_list if x!='']
print char_list
# output
['', ' a', 'b', '\t']
['a', 'b', '']
#DESIRED output
['', ' a', 'b', '\t']
['a', 'b']
char_list = [x.strip() for x in char_list if x.strip()]
你想要的是删除无用的字符串。 x!="" 无法删除 "\t".
通常在这种情况下,我会将其更改为 2 个步骤...在第一步中,我会进行可能代价高昂的处理。在第二步中,我进行过滤。第一步可以使用生成器表达式来避免不必要的列表:
char_list_stripped = (x.strip() for x in char_list)
char_list = [x for x in char_list_stripped if x]
在这种情况下,它使您免于调用 x.strip
的次数是您实际需要的次数的两倍(如果您将其全部打包到一个推导式中)。这可能不会 巨大 节省(您可能不会注意到速度差异)。但在更一般的情况下,它可能会产生重大差异,具体取决于处理实际需要多少工作。
两次调用 strip() 的双重理解将比单一理解更有效
char_list = [ x for x in [ x.strip() for x in char_list ] if x ]
>>> char_list = ['', ' a','b', '\t']
>>> filter(None, map(str.strip, char_list))
['a', 'b']
在蜘蛛中硬编码这些东西不是一个好习惯。查看 Scrapy 的 built-in Item Loader 和 input/output 处理器。 在您的 REPL 中尝试以下操作:
from scrapy.contrib.loader.processor import MapCompose
def compact(s):
""" returns None if string is empty, otherwise string itself """
return s if s else None
char_list = ['', ' a','b', '\t']
MapCompose(unicode.strip, compact)(char_list)
=> ['a', 'b']
MapCompose 按顺序对每个项目应用给定的函数,每个函数将一个项目作为参数,从以后的处理中排除 None。
在您的 items.py:
中使用此方法的最简单方法# -*- coding: utf-8 -*-
import scrapy
from scrapy.contrib.loader.processor import MapCompose
def compact(s):
return s if s else None
class MyItem(scrapy.Item):
my_field = scrapy.Field(
input_processor=MapCompose(unicode.strip, compact)
)
并且在您的蜘蛛 parse_my_items 回调中:
from scrapy.contrib.loader import ItemLoader
from myproject.items import MyItem
il = ItemLoader(item=MyItem())
il.add_value('my_field', char_list)
my_item = il.load_item()
yield my_item
#=> {'my_field': [u'a', u'b']}
希望对您有所帮助!