I'm trying to calculate the number of words in a file using reduce
, lambda
& readlines
in an unconventional way:
import functools as ft
f=open("test_file.txt")
words=ft.reduce(lambda a,b:(len(a.split())+len(b.split())),f.readlines())
print(words)
This raises an attribute error as I'm trying to split integers (indices). How do I get this code to split the elements of the iterable returned by f.readlines()
and successively add their lengths (i.e, number of words in those lines) to ultimately calculate the total number of words in the file?
If you're trying get a count of words in a file, f.read()
makes more sense than f.readlines()
because it obviates the need to sum line-by-line counts. You get the whole file in a chunk and can then split on whitespace using split
without arguments.
>>> with open("foo.py") as f:
... len(f.read().split())
...
1530
If you really want to use readlines
, it's easier to avoid functools.reduce
in any event and sum
the lengths of the split
lines (sum
is a very succinct reduction operation on an iterable that does away with the distracting accumulator business):
>>> with open("foo.py") as f:
... sum(len(x.split()) for x in f.readlines())
...
1530
It's good practice to use a with
context manager so your resource is automatically closed. Use whitespace around all operators so the code is readable.
As for getting functools.reduce
to work: it accepts a lambda which accepts the accumulator as its first argument and the current element as the second. The second argument to functools.reduce
is an iterable and the third initializes the accumulator. Leaving it blank as you've done sets it to the value of the first item in the iterable--probably not what you want, since the idea is to perform a numerical summation using the accumulator.
You can use
>>> with open("foo.py") as f:
... ft.reduce(lambda acc, line: len(line.split()) + acc, f.readlines(), 0)
...
1530
but this strikes me as a rather Rube Goldbergian way to solve the problem.