如何排序和保持列表的完整性?

时间:2012-09-16 16:05:10

标签: python sorting

所以我写的脚本有一个小问题。我有一个看起来像这样的文本文件:

'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 个答案:

答案 0 :(得分: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的建议。

[编辑以保持所有字符串]

答案 1 :(得分:1)

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

所以你的例子就是

1,2,1,2。

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

比用第3个字符串中的每个1替换下一个数字,每个2用下一个字符串替换。

它应该完美无缺。

答案 2 :(得分: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斑马12 17牛熊'),你可以使用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

答案 3 :(得分: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