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

您需要做的是创建第三个列表。数字为 1,字符串为 2。

所以你的例子是

1、2、1、2。

比您将所有数字放在一个列表中,将字符串放在第二个列表中。对它们进行排序。

然后将第三个字符串中的每个 1 替换为下一个数字,并将每个 2 替换为下一个字符串。

它应该可以完美运行。

于 2012-09-16T16:24:01.210 回答
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

对于一般情况下,内容可能无法完美交错(例如'20 15 zebra 12 17 cow Bear'),您可以使用 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 回答
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 回答