【问题标题】:python binary search and file i/opython二进制搜索和文件i/o
【发布时间】:2014-03-12 15:04:24
【问题描述】:

这是我遇到的作业的一部分... 我是 python 新手,我想创建一个程序来搜索一个看起来像这样的文件,但时间更长:

Afghanistan,    647500.0,   25500100
Albania,    28748.0,    2821977
Algeria,    2381740.0,  38700000
American Samoa, 199.0,  55519

如您所见,间距并不总是均匀的...我想将文本部分转换为字符串,将区域(第二列)转换为浮点数,将第三列(人口)转换为整数,但没有想法如何处理它。 这是我目前所拥有的:

def readcountries():
    with open("countries.txt") as file:
        lines = [line.split() for line in file]

返回一个二维列表(这是必需的)...但我不知道如何将区域和人口转换为适当的类型。然后我必须对国家名称进行二进制搜索>任何提示?我知道如何在数字上执行此操作,但在名称上?

【问题讨论】:

标签: python sorting search file-io binary-search


【解决方案1】:

这里不要使用列表推导;可以做到,但很快就会变得丑陋:

def readcountries():
    with open("countries.txt") as fh:
        rows = []
        for line in fh:
            name, area, population = line.split(',')
            rows.append([name.strip(), float(area), int(population)])

列表理解版本是:

def readcountries():
    with open("countries.txt") as fh:
        rows = [[n.strip(), float(a), int(p)] 
                for line in fh for n, a, p in (line.split(','),)]

使用csv module 可以节省一些处理时间:

import csv

def readcountries():
    with open("countries.txt") as fh:
        reader = csv.reader(fh, skipinitialspace=True)
        rows = [[n, float(a), int(p)] for n, a, p in reader]

这里模块处理拆分和剥离,为每一行生成列表对象。

对于二分搜索,Python 允许您将字符串与<> 进行比较;字符串按字典顺序进行比较。 ab 小于 ac,但 ba 大于 ab。换句话说,将在另一个字符串之前排序的字符串被认为是“更小”。

因此,对已排序字符串列表的二进制搜索与对已排序数字列表的二进制搜索没有什么不同。请确保您只查看元组的第一个元素:

def bisect_right(rows, country, lo=0, hi=None):
    if hi is None:
        hi = len(rows)
    while lo < hi:
        mid = (lo + hi) // 2
        if country < rows[mid][0]:
            hi = mid
        else:
            lo = mid + 1
    return lo

def bisect_left(rows, country, lo=0, hi=None):
    if hi is None:
        hi = len(rows)
    while lo < hi:
        mid = (lo + hi) // 2
        if rows[mid][0] < country:
            lo = mid + 1
        else:
            hi = mid
    return lo

【讨论】:

  • line.split() 应该是 line.split(',')
  • @JayanthKoushik: [[n, float(a), int(p)] for line in file for n, a, p in (line.split(','),)]
  • 好吧,您将 strip() 移到 append 的原因。感谢您的技巧
  • 您的索引有点不合常规:pastebin.com/etPVDYWU 我希望它们从 0 开始。
  • @hughdbrown:这是一个bisect_right;找到插入新值的点。
【解决方案2】:

您可以创建一个包含成员名称、人口和地区的类 Country

class Country:
    def __init__(self,name,area,population):
        self.name = name
        self.area = area
        self.population = population

尝试使用此代码读取文件并对其进行解析,然后对国家对象数组进行排序:

def readcountries():
    countries_array = []
    with open("countries.txt") as file:
        lines = [line.split(',') for line in file]
    for line in lines:
        country = line[0].strip(' ')
        area = line[1].strip(' ')
        population = line[2].strip(' ')
        countries_array.append(Country(country, area, population))

    sorted_countries = sorted(countries_array,key=operator.attrgetter('name'))
    print [country.name for country in sorted_countries]

【讨论】:

  • 或:country, area, population = (item.strip(' ') for item in line)
【解决方案3】:

使用逗号作为分隔符而不是默认的空格进行分割。 split 为此使用了一个参数。每行将被拆分为一个三元素列表。您需要使用 intfloat 函数将第二个和第三个条目从字符串转换为数字。

编辑:这部分 Python 教程有一些 information about lists

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-26
    • 2015-01-29
    • 2016-06-15
    • 2014-07-06
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多