0

だから、私が書いているスクリプトに小さな問題があります。次のようなテキストファイルがあります。

'20 zebra 12 bear'

これは単なる例です。形式は、すべての項目がスペースで区切られた 1 行です。スクリプトはそれらを整理し、文字列に対して他のいくつかのことを行うように機能しますが、私が理解できないのは、それをそのままの状態に保つ方法です。たとえば、上記の行は次のように並べ替える必要があります。

12
bear
20
zebra

数字を数字の場所に、文字列を文字列の場所に保持する必要がありますが、それらは英数字順に並べ替える必要があります。これまでの私のスクリプトは次のとおりです。

#!/usr/bin/python

# Make sure you use the proper modules.
import sys, string

# This area defines the arguments and returns a usage message should it be used incorrectly.
try:
  infilename = sys.argv[1]; outfilename = sys.argv[2]
except:
  print "Usage:",sys.argv[0], "infile outfile"; sys.exit(1)

ifile = open(infilename, 'r') # Opens the input file for reading
ofile = open(outfilename, 'w') # Opens the output file for writing
data = ifile.readlines()[0].split() # Reads the lines on the input file

# The items in the list are sorted here and defined by a space.
sort = sorted(data, key=lambda item: (int(item.partition(' ')[0])
                                   if item[0].isdigit() else float('inf'), item))

# Use this to remove any special characters in the list
filtered = [s.translate(None, string.punctuation) for s in sort]


ofile.write('\n'.join(filtered)) # Writes the final output to file (one on each line)



ifile.close() # Closes the input file
ofile.close() # Closes the output file

私はそれが最もきれいではないことを知っていますが、私はPythonを長く使用していないので、よりきれいにする方法について提案があれば、私はすべて聞いています. 私が本当に必要としているのは、数字を数字に、文字列を文字列に保ち、それらを入れ替えてソートすることだけです。与えられた援助に感謝します。

4

4 に答える 4

2

これは本当に奇妙な質問です。

def strange_sort(seq):
    """
    Sorts digitstrings (by integer value) and non-digitstrings in a
    sequence among themselves, preserving the original ds/non-ds
    signature.
    """
    numbers = iter(sorted((elem for elem in seq if elem.isdigit()), key=int))
    words = iter(sorted(elem for elem in seq if not elem.isdigit()))
    final = [next(numbers if elem.isdigit() else words) for elem in seq]
    return final

これは

>>> strange_sort("1 2 3".split())
['1', '2', '3']
>>> strange_sort("1 2 10 3".split())
['1', '2', '3', '10']
>>> strange_sort("1 2 10 3 bear".split())
['1', '2', '3', '10', 'bear']
>>> strange_sort("2 1 bear 10 3".split())
['1', '2', 'bear', '3', '10']
>>> strange_sort("2 1 zebra 10 3 bear".split())
['1', '2', 'bear', '3', '10', 'zebra']
>>> strange_sort("20 zebra 12 bear".split())
['12', 'bear', '20', 'zebra']
>>> strange_sort("20 zebra 12 bear 3".split())
['3', 'bear', '12', 'zebra', '20']

実際、これは基本的に@przemo_liの提案がうまくいったことです。

[すべてを文字列に保つように編集]

于 2012-09-16T16:39:26.880 に答える
1

インターリーブされた数値と文字列の特定のケースでは、リストスライスを使用します。

text = '20 zebra 12 bear 5 moose'
arr = text.split()
arr[::2] = sorted(arr[::2], key=int)
arr[1::2] = sorted(arr[1::2])

print ' '.join(arr)

出力:

5 bear 12 moose 20 zebra

コンテンツが完全にインターリーブされていない可能性がある一般的なケース(たとえば、「2015ゼブラ1217カウベア」)では、Numpyを使用できます。

import numpy as np

text = '20 15 zebra 12 17 cow bear 5 2 1'
arr = np.char.array(text.split())
nums = arr.isdigit()
strs = ~nums
arr[nums] = sorted(arr[nums], key=int)
arr[strs] = np.sort(arr[strs])

print ' '.join(arr)

出力:

1 2 bear 5 12 cow zebra 15 17 20
于 2012-09-16T16:35:44.403 に答える
1

あなたがする必要があるのは、3番目のリストを作成することです. 数値は 1、文字列は 2 です。

だからあなたの例は

1、2、1、2。

すべての数字を 1 つのリストに入れ、文字列を 2 番目に入れます。それらを並べ替えます。

3 番目の文字列の各 1 を次の番号に置き換え、各 2 を次の文字列に置き換えます。

それは完全に機能するはずです。

于 2012-09-16T16:24:01.210 に答える
0

私は次のようにします:

  • たとえば を使用して、リストをトークンに分割しますre.split
  • リスト スライスを使用して、キー (数字) のリストと値 (単語) のリストを作成します。
  • このタプルのリストをソートします。(これで正しくソートされます)

その後、文字列に戻す必要がある場合:

  • タプルの要素をスペースで結合します。
  • 結果のリストをスペースで結合します。

これを行うコードは次のとおりです。

#!/usr/bin/python
import re

data = "12 foo 35 bar 10 baz 23 foobar"

d = re.split("\s+", data)
tuples = zip(d[0::2], d[1::2])
tuples.sort()

# If you need it back to a string
dsorted = [x + " " + y for (x, y) in tuples]
datasorted = " ".join(dsorted)

print data
print datasorted

これにより、次が出力されます。

12 foo 35 bar 10 baz 23 foobar
10 baz 12 foo 23 foobar 35 bar
于 2012-09-16T16:23:54.253 に答える