如何从列表元素中移除 \n?

96
我正在尝试让Python读取一个.txt文件中的一行,并将第一行的元素写入一个列表中。文件中的元素是由制表符分隔的,所以我使用了split("\t")将元素分离。因为.txt文件有很多元素,所以我将每行数据保存到了单独的列表中。
目前我遇到的问题是显示每个列表如下:
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']

如何将列表中的最后一个元素的 \n 去除,并使其变为 '7.3'


使用您拥有的数据,只需使用split()(无参数)。它将首先剥离空格,然后在空格上进行分割。 - JoshD
15个回答

166
如果您只想从最后一个元素中删除\n,请使用以下方法:
t[-1] = t[-1].strip()

如果您想从所有元素中删除\n,请使用以下方法:
t = map(lambda s: s.strip(), t)

您可以考虑在分割行之前删除\n
line = line.strip()
# split line...

7
我会在分割之前去除一些内容……我觉得这样更加简洁。 - st0le
10
如果我要迭代这个列表,我也会使用[s.strip() for s in t]。我测试了一下,处理["s\n"]*10000需要5.33毫秒,而使用map则需要9.73毫秒。如果映射的是内置函数,那么map会更快。 - aaronasterling
3
line = line.strip()会移除所有行末的空格,这是不必要的操作,可以参考Jim Dennis的回答。 - John Machin
1
@John True。不仅如此,它还会删除所有前导空格。在许多情况下,line.strip()line.rstrip('\n')更合理,这就是为什么我没有进一步解释它的原因。然而,在这种情况下(制表符分隔值),您是100%正确的:确实应该小心地删除前导和尾随空格,因为第一列或最后一列为空可能会“消失”。 - Bolo
我有一个列表 contents=['1 148766 15417.5 0.867096 2.00747 1.67202 [198.969, 189.629, 78.7315] [118.66, 120.51, 238.207] [117, 241, 83, 274, 23, 135] \n', '2 ...],其中每个元素都以\n结尾。内容的长度为3。如何从列表的每个元素中删除此行,并将列表保存到numpy数组中。 - sc241
@sc241,你应该在StackOverflow上创建一个单独的问题,而不是仅仅留下评论,因为你的问题涉及到远比去除'\n'更多的内容。在你的问题中,请指定你对于所提供的输入所期望的确切输出 - 这将有助于澄清你的需求。 - Bolo

72

从Python3开始

map不再返回list而是一个mapObject,因此答案会类似于:

>>> map(lambda x:x.strip(),l)
<map object at 0x7f00b1839fd0>

您可以在Python 3.0的新特性中了解更多相关信息。

map()filter()返回迭代器。如果您确实需要一个list,一个快速的解决方法是使用list(map(...))

那么现在有哪些方法可以通过这个呢?


案例1 - 使用lambdamap调用 list

map返回一个迭代器。list是一个可以将迭代器转换为列表的函数。因此,您需要在map周围包装一个list调用。 因此,现在的答案变成了:

>>> l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']
>>> list(map(lambda x:x.strip(),l))
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

非常好,我们得到了输出。现在我们需要检查这段代码执行所需的时间。
$ python3 -m timeit "l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n'];list(map(lambda x:x.strip(),l))"
100000 loops, best of 3: 2.22 usec per loop

2.22微秒。这并不算糟糕。但是否有更有效的方法呢?


案例2 - 不使用lambdamap调用列表

lambda在Python社区中被许多人(包括Guido)所反对。除此之外,它会极大地降低程序的速度。因此,我们需要尽可能避免使用它。顶层函数str.strip在这里帮了我们的忙。

可以使用str.strip重新编写不使用lambdamap,如下所示:

>>> list(map(str.strip,l))
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

现在是时间。

$ python3 -m timeit "l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n'];list(map(str.strip,l))"
1000000 loops, best of 3: 1.38 usec per loop

太棒了。你可以看到这两种方法之间的效率差异。使用lambda表达式的方法快了近60%,因此在这里不使用lambda表达式的方法是更好的选择。


案例三 - 遵循指南,常规方式

Python 3.0的新特性中的另一个重要观点是尽可能避免使用map

特别棘手的是为了函数的副作用而调用map();正确的转换方式是使用常规的for循环(因为创建列表只会浪费空间)。

因此,我们可以通过使用常规的for循环来解决这个问题,而不需要使用map

解决问题的简单方法(暴力方法)是:

>>> l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']
>>> final_list = []
>>> for i in l:
...     final_list.append(i.strip())
... 
>>> final_list
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

计时设置
def f():
    l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']
    final_list = []
    for i in l:
         final_list.append(i.strip())
import timeit
print(min(timeit.repeat("f()","from __main__ import f")))

和结果。

1.5322505849981098

如您所见,暴力算法在此处稍慢。但它对于一般程序员来说肯定比map子句更易读。


案例4 - 列表推导式

这里也可以使用列表推导式,与Python2中相同。

>>> [i.strip() for i in l]
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

现在是关于时间安排的:
$ python3 -m timeit "l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n'];[i.strip() for i in l]"
1000000 loops, best of 3: 1.28 usec per loop

正如您所看到的,列表推导式比map更有效(即使没有lambda)。因此,在Python3中的经验法则是使用列表推导式而不是map

案例5 - 就地机制和空间效率 (T-M-T)

最后一种方法是直接在列表中就地进行更改。这将节省大量内存空间。可以使用 enumerate 来实现。

>>> l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']
>>> for i,s in enumerate(l):
...     l[i] = s.strip()
... 
>>> l
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

时间结果将为1.4806894720022683。但是这种方法的空间效率很高。

结论

一个时间比较列表(包括Python 3.4.3和Python 3.5.0)

----------------------------------------------------
|Case| method          | Py3.4 |Place| Py3.5 |Place|
|----|-----------------|-------|-----|-------|-----|
| 1  | map with lambda | 2.22u | 5   | 2.85u | 5   |
| 2  | map w/o lambda  | 1.38u | 2   | 2.00u | 2   |
| 3  | brute-force     | 1.53u | 4   | 2.22u | 4   |
| 4  | list comp       | 1.28u | 1   | 1.25u | 1   |
| 5  | in-place        | 1.48u | 3   | 2.14u | 3   |
----------------------------------------------------

最后请注意,列表推导式是最好的方式,map和使用lambda是最差的。但是再次强调 --- 仅适用于Python3


11

听起来你想要像Perl的chomp()函数那样的东西。

在Python中做这很容易:

def chomp(s):
    return s[:-1] if s.endswith('\n') else s

假设您正在使用Python 2.6或更高版本。否则,只需使用略微冗长的:

def chomp(s):
    if s.endwith('\n'):
        return s[:-1]
    else:
        return s
如果您想从字符串末尾删除所有换行符(在某些情况下可能会有多个尾随换行符的奇怪情况),则可以:
def chomps(s):
    return s.rstrip('\n')

显然你不应该从任何正常的Python文件对象的readline()readlines()方法中看到这样的字符串返回。

我见过人们盲目地从文件的readline()等函数的结果中去掉最后一个字符(使用s[:-1]切片)。这是一个坏主意,因为它可能导致文件的最后一行错误(在文件以除了换行符之外的任何其他字符结尾的情况下)。

起初,当你盲目地剥离已读取行的最后字符时,你可能会被安全感蒙蔽。如果你使用普通文本编辑器创建测试套件文件,大多数编辑器都会自动在最后一行的末尾添加一个换行符。要创建有效的测试文件,请使用类似以下的代码:

f = open('sometest.txt', 'w')
f.write('some text')
f.close()

如果您重新打开该文件并在其上使用 readline()readlines() 文件方法,您会发现文本被读取时不带有尾随的换行符。

许多UNIX实用程序和脚本语言多年来一直存在这种未考虑以非换行符结尾的文本文件的问题。这是一个愚蠢的角落错误,它经常潜入代码中,足以成为一个麻烦,但又不足以让人们从中学到什么。我们可以争论说没有最终换行符的“文本”文件是“损坏”的或者不符合标准;对于某些编程规范而言,这可能是有效的。

然而,在我们编码时忽略边缘情况并使那种无知伤害依赖您代码的人变得非常容易。就像我妻子所说的那样:当涉及编程时...请小心处理!


1
在读取Python文本文件时,应该先检查换行符是否存在(或者如果存在就盲目地将其删除,例如line = line.rstrip('\n')),然后再将该行解析为字段。这个步骤应该是分开进行的。 - John Machin

6
使用列表推导式:
myList = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']

[(el.strip()) for el in myList]

这意味着意图是去除所有前导和尾随的空格。这并不完全匹配“删除尾随换行符”。 - Jim Dennis

4
new_list = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']
for i in range(len(new_list)):
    new_list[i]=new_list[i].replace('\n','')
print(new_list)

输出结果将如下所示。
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

3

从这个链接中:

你可以使用rstrip()方法。例如:

mystring = "hello\n"    
print(mystring.rstrip('\n'))

2

您需要访问集合的最后一个元素,并将其存储在变量中。

因此,您需要执行以下操作:

fileName = '7.3\n'

那就只需执行以下操作:
fileName.strip()

这将使您得到7.3的值。然后将该值存储回集合的最后一个元素。

您可以使用lstrip()rstrip()仅删除左侧或右侧。


2
作为一种替代方法,如果您知道您的数据中没有空格,似乎是这种情况,您可以使用split()(不带参数)。它会在空格处进行分割,并使用比另一个版本的split更高效的算法。它还会去掉两端的空格。
line = line.split()

就这样。


2

您可以做的事情:

DELIMITER = '\t'
lines = list()
for line in open('file.txt'):
    lines.append(line.strip().split(DELIMITER))
< p > lines 包含了文件的所有内容。

你也可以使用列表推导式使其更加简洁。

lines = [ line.strip().split(DELIMITER) for line in open('file.txt')]

我正在使用这种方法的变体将文件转换为单行JavaScript变量。不错。谢谢Srikar。 - zach

2

str.strip()函数可以去除字符串中的空白字符,你也可以传入自定义字符作为参数进行去除。strip函数会在字符串两端去除空白字符或自定义字符。lstrip()和rstrip()分别是左侧去除和右侧去除函数。

例如:

test_str = "Vishaka\n" 
test_str = test_str.strip()

test_str现在是Vishaka


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接