0

I have a text file with a location and its coordinates on a new line e.g.

A&AB
42.289567
-83.717143
AH
42.276620
-83.739620)

I have a for loop that iterates through this list and if the location matches the user input, it returns the next two lines (latitude and longitude). How do I do this in a neat fashion using Python? I know how to do this in C++ but I have no idea with Python.

Alex K
  • 8,269
  • 9
  • 39
  • 57
Amanda
  • 13
  • 1

6 Answers6

1

Python iterators can be advanced manually, as well as implicitly. Assuming you'll only be reading a single value, not checking over and over (and don't want to store all values in memory for whatever reason), you could do:

def find_latlong(locname, locfile):
    with open(locfile) as f:
        for line in f:
            if line.rstrip() == locname:
                try:
                    return float(next(f)), float(next(f))
                except StopIteration:
                    break
    raise ValueError("location {!r} not found".format(locname))

This just looks for the line matching the provided name in the provided file, and manually iterates to get the next two lines when it is found.

An alternative that assumes the exact three line pattern, and doesn't check the non-name lines:

from future_builtins import map, zip  # Only on Python 2

def find_latlong(locname, locfile):
    with open(locfile) as f:
        f = map(str.rstrip, f)
        for header, lat, lng in zip(f, f, f):  # Reads three lines at a time
            if header == locname:
                return float(lat), float(lng)
    raise ValueError("location {!r} not found".format(locname))
ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
1

Here's yet another approach to the same soup:

def match(name):
    with open("locat.txt") as f:
        #gr = [iter(f)]*3
        #for tag lat, lon in zip(*gr):
        for tag, lat, lon in zip(f, f, f):
            if tag.rstrip() == name:
                return float(lat.rstrip('\n)')), float(lon.rstrip('\n)'))
    return None

print(match('AY'))
print(match('xy'))

produces

(42.27, -83.73)
None

It only tries to match the given name to every third line and it returns None if no match is found.

Note: there is no error checking, so you need to be sure the input data is correct (e.g. if any of the entries lack a row, i.e. a coordinate value, it would not work. In such case one of the other answers above which check the match against each row would work better and re-synch automatically).

Pynchia
  • 10,996
  • 5
  • 34
  • 43
  • @PadraicCunningham I know, in fact it was working fine. I did it to enable it to remove the parens in one go, otherwise `rstrip` would find the \n only – Pynchia Dec 08 '15 at 00:04
  • You can forget the zip iter though, you already have an iterator you can simply `zip(f,f,f)` – Padraic Cunningham Dec 08 '15 at 00:10
1
from itertools import dropwhile
def get_data(fle, lne):
    with open(fle) as f:
        dw = dropwhile(lambda x: x.rstrip() != lne,f)
        _, a, b = next(dw,""), next(dw, "").rstrip(")\n"), next(dw,"").rstrip(")")
        return  (a,b) if b else (None, None)

lat, lon = get_data("foo.txt","A&AB")
if lat:
   # you have a match 
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
-1

Check out this answer for some great options Click here. The simplest answer is that you can use the in operator, or matches = [x for x in lst if fulfills_some_condition(x)]. But click on the above link for a more detailed answer. Assuming, of course, that you are iterating through a list as described.

Community
  • 1
  • 1
-1

As a language, Python emphasizes readability. In addition to advanced solutions using iterators provided by others, here is one using the simple readline method on the file object:

with open(filename) as f:
    while True:
        desc =f.readline()
        lat = f.readline()
        lng = f.readline()
        if not desc:
            return None, None
        if desc.strip() == wanted:
            return float(lat), float(lng)
user4815162342
  • 141,790
  • 18
  • 296
  • 355
-2

I think what you can do is build a list of tuples, where each tuple will be of the type (Location,Latitude,Longitude)

You can do that as follows :

with open("filename","r") as f:
    lines = f.readlines()

# This is essentially splitting the lines into 
# locations, latitudes and longitudes and then merges them using zip
# to get a list of tuples
locations = zip(lines[0::3],lines[1::3], lines[2::3])

# Assuming that the userLocation contains user input
userLocation = 'foobar'

# Find the user input in our list
result = [x for x in locations if locations[0] == userLocation]

# Print the matches
for r in results:
    print "Latitude = " + str(r[1]) + "   Longitude = " + str(r[2])
Abhinav Arora
  • 3,281
  • 18
  • 20
  • This is a very poor way to tackle the problem so I can see exactly why it was downvoted, you keep multiple copies in memory when there is no need to at all – Padraic Cunningham Dec 07 '15 at 23:57
  • @PadraicCunningham - If I free off the memory for locations list, then how would it consume extra memory? – Abhinav Arora Dec 08 '15 at 00:29
  • Where are you freeing of memory? Every answer has managed to solve the problem by only keeping at most a few lines in memory, yours has the whole file and then some – Padraic Cunningham Dec 08 '15 at 00:48