2012-03-31 6 views
3

を使用している場合:ソートの問題私は、IPアドレスのリストが含まれている.txtファイル持っているリスト

111.67.74.234:8080 
111.67.75.89:8080 
12.155.183.18:3128 
128.208.04.198:2124 
142.169.1.233:80 

をそれにもかかわらずよりも多くあります:)

とにかく、リストにこれをインポートPythonを使用して、私はそれを並べ替えるようにしようとしていますが、私は問題を抱えています。誰にもアイデアはありますか?

編集: それはあいまいだったので、これは私がとても公平だったからです。

f = open("/Users/jch5324/Python/Proxy/resources/data/list-proxy.txt", 'r+') 
lines = [x.split() for x in f] 
new_file = (sorted(lines, key=lambda x:x[:18])) 
+3

「私は悩みを抱えている」強大な非特異的です。何を試しましたか?どのように失敗しましたか? – kindall

+0

「困っている」というのはあまり役に立ちません。 "私はXを試しましたが、Yのやり方では動作しません。そして/またはエラーZを与えてくれます。" –

+0

どのような基準でソートしますか?ファイルをロードして、エントリを分離し、それらをリストオブジェクトに入れることさえできましたか?あなたはどこにいますか? –

答えて

5

おそらく、ASCII文字列-比較することによって、それらを仕分けしている(「」< 『5』など)、するときには、むしろその彼らソート数値的に思います。その後、並べ替え、int型のタプルに変換してみてください。

def ipPortToTuple(string): 
    """ 
     '12.34.5.678:910' -> (12,34,5,678,910) 
    """ 
    ip,port = string.strip().split(':') 
    return tuple(int(i) for i in ip.split('.')) + (port,) 

with open('myfile.txt') as f: 
    nonemptyLines = (line for line in f if line.strip()!='') 
    sorted(nonemptyLines, key=ipPortToTuple) 

編集:あなたのテキストファイルが#ではないのでとValueErrorあなたが取得しているある###:。。。#フォーマットあなたが暗示するように。 (コメントや空白行があるかもしれませんが、この場合、エラーには複数の ':'が含まれることがあります)。デバッグデータ:。。。。


def tryParseLines(lines): 
    for line in lines: 
     try: 
      yield ipPortToTuple(line.strip()) 
     except Exception: 
      if __debug__: 
       print('line {} did not match #.#.#.#:# format'.format(repr(line))) 

with open('myfile.txt') as f: 
    sorted(tryParseLines(f)) 
は、私はそれはまだ(例えば#を通していくつかの無効なIPアドレスをすることができますように###、#上記のビットずさんだった、または257-1。 #。#)。以下は、あなたも自然に仕事をソートすること、 <事業者とIPアドレスを比較するようなことを行うことができ、より徹底したソリューションです:

#!/usr/bin/python3 

import functools 
import re 

@functools.total_ordering 
class Ipv4Port(object): 
    regex = re.compile(r'(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}):(\d{1,5})') 

    def __init__(self, ipv4:(int,int,int,int), port:int): 
     try: 
      assert type(ipv4)==tuple and len(ipv4)==4, 'ipv4 not 4-length tuple' 
      assert all(0<=x<256 for x in ipv4), 'ipv4 numbers not in valid range (0<=n<256)' 
      assert type(port)==int, 'port must be integer' 
     except AssertionError as ex: 
      print('Invalid IPv4 input: ipv4={}, port={}'.format(repr(ipv4),repr(port))) 
      raise ex 

     self.ipv4 = ipv4 
     self.port = port 

     self._tuple = ipv4+(port,) 

    @classmethod 
    def fromString(cls, string:'12.34.5.678:910'): 
     try: 
      a,b,c,d,port = cls.regex.match(string.strip()).groups() 
      ip = tuple(int(x) for x in (a,b,c,d)) 
      return cls(ip, int(port)) 
     except Exception as ex: 
      args = list(ex.args) if ex.args else [''] 
      args[0] += "\n...indicating ipv4 string {} doesn't match #.#.#.#:# format\n\n".format(repr(string)) 
      ex.args = tuple(args) 
      raise ex 

    def __lt__(self, other): 
     return self._tuple < other._tuple 
    def __eq__(self, other): 
     return self._tuple == other._tuple 

    def __repr__(self): 
     #return 'Ipv4Port(ipv4={ipv4}, port={port})'.format(**self.__dict__) 
     return "Ipv4Port.fromString('{}.{}.{}.{}:{}')".format(*self._tuple) 

、その後:

def tryParseLines(lines): 
    for line in lines: 
     line = line.strip() 
     if line != '': 
      try: 
       yield Ipv4Port.fromString(line) 
      except AssertionError as ex: 
       raise ex 
      except Exception as ex: 
       if __debug__: 
        print(ex) 
       raise ex 

デモ:

>>> lines = '222.111.22.44:214 \n222.1.1.1:234\n 23.1.35.6:199'.splitlines() 
>>> sorted(tryParseLines(lines)) 
[Ipv4Port.fromString('23.1.35.6:199'), Ipv4Port.fromString('222.1.1.1:234'), Ipv4Port.fromString('222.111.22.44:214')] 

値をたとえば264...または...-35...に変更すると、適切なエラーが発生します。

+0

データ内の空白行、コメントなど、IP:portアドレスとまったく同じではないものをすべて削除します。 –

+0

(または、エラーチェック/例外処理を追加して、エラーが正常に処理されるようにしてください) –

+0

動作しませんでした.... ValueError:アンパックする値が多すぎますか? – h3tr1ck

-1

組み込みの比較関数を使用して並べ替えることができるように、リストを事前処理することができます。それを通常の形式に戻して処理します。

文字列は同じ長さになり、並べ替えることができます。その後、すべてのスペースを単に削除します。

あなたはGoogleの周りにこれの他の例を見つけることができます。あなたは、IPアドレスのトンを持っている場合

for i in range(len(address)): 
    address[i] = "%3s.%3s.%3s.%3s" % tuple(ips[i].split(".")) 
address.sort() 
for i in range(len(address)): 
    address[i] = address[i].replace(" ", "") 

はあなたがC++のを使用する場合は、より良い処理時間を得ようとしています。それはより多くの作業が前面になりますが、より良い処理時間が得られます。 Ninjageckoのソリューション@

+1

これは '.sort()'の重要な機能としてよく扱われます。 DSU(decorate-sort-undecorate)は、現代のPythonでこれを処理する最良の方法ではありません。 – kindall

0

が最良であるが、ここで再使用してそれを行うための別の方法である:

>>> import re 
>>> with open('ips.txt') as f: 
     print sorted(f, key=lambda line: map(int, re.split(r'\.|:', line.strip()))) 


['12.155.183.18:3128\n', '111.67.74.234:8080\n', '111.67.75.89:8080\n', 
'128.208.04.198:2124\n', '142.169.1.233:80 \n'] 
関連する問題