简体   繁体   中英

get nth line of string in python

How can you get the nth line of a string in Python 3? For example

getline("line1\nline2\nline3",3)

Is there any way to do this using stdlib/builtin functions? I prefer a solution in Python 3, but Python 2 is also fine.

Try the following:

s = "line1\nline2\nline3"
print s.splitlines()[2]

a functional approach

>>> import StringIO
>>> from itertools import islice
>>> s = "line1\nline2\nline3"
>>> gen = StringIO.StringIO(s)
>>> print next(islice(gen, 2, 3))
line3

Use a string buffer:

import io    
def getLine(data, line_no):
    buffer = io.StringIO(data)
    for i in range(line_no - 1):
        try:
            next(buffer)
        except StopIteration:
            return '' #Reached EOF

    try:
        return next(buffer)
    except StopIteration:
        return '' #Reached EOF

From the comments it seems as if this string is very large. If there is too much data to comfortably fit into memory one approach is to process the data from the file line-by-line with this:

N = ...
with open('data.txt') as inf:
    for count, line in enumerate(inf, 1):
        if count == N: #search for the N'th line
            print line

Using enumerate() gives you the index and the value of object you are iterating over and you can specify a starting value, so I used 1 (instead of the default value of 0)

The advantage of using with is that it automatically closes the file for you when you are done or if you encounter an exception.

A more efficient solution than splitting the string would be to iterate over its characters, finding the positions of the Nth and the (N - 1)th occurence of '\\n' (taking into account the edge case at the start of the string). The Nth line is the substring between those positions.

Here's a messy piece of code to demonstrate it (line number is 1 indexed):

def getLine(data, line_no):
    n = 0
    lastPos = -1
    for i in range(0, len(data) - 1):
        if data[i] == "\n":
            n = n + 1
            if n == line_no:
                return data[lastPos + 1:i]
            else:
                lastPos = i;



    if(n == line_no - 1):
        return data[lastPos + 1:]
    return "" # end of string

This is also more efficient than the solution which builds up the string one character at a time.

Since you brought up the point of memory efficiency, is this any better:

s = "line1\nline2\nline3"

# number of the line you want
line_number = 2

i = 0
line = ''
for c in s:
   if i > line_number:
     break
   else:
     if i == line_number-1 and c != '\n':
       line += c
     elif c == '\n':
       i += 1

Wrote into two functions for readability

    string = "foo\nbar\nbaz\nfubar\nsnafu\n"

    def iterlines(string):
      word = ""
      for letter in string:
        if letter == '\n':
          yield word
          word = ""
          continue
        word += letter

    def getline(string, line_number):
      for index, word in enumerate(iterlines(string),1):
        if index == line_number:
          #print(word)
          return word

    print(getline(string, 4))
`my_string.strip().split("\n")[-1]`

My solution (effecient and compact):

def getLine(data, line_no):
    index = -1
    for _ in range(line_no):index = data.index('\n',index+1)
    return data[index+1:data.index('\n',index+1)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM