【问题标题】:How to split a mixed string with numbers如何用数字拆分混合字符串
【发布时间】:2015-12-30 17:19:32
【问题描述】:

我的文本文件中有一个数据,其中包含“Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002”。

是否可以在不使用“Test DATA_”字样的情况下对其进行排序,以便将数据排序为 g001、g002、g003 等?

我尝试了.split("Test DATA_") 方法,但它不起作用。

def readFile():
    #try block will execute if the text file is found
    try:
        fileName = open("test.txt",'r')
        data = fileName.read().split("\n")
        data.sort (key=alphaNum_Key) #alternative sort function
        print(data)
    #catch block will execute if no text file is found
    except IOError:
        print("Error: File do not exist")
        return

#Human sorting
def alphaNum(text):
    return int(text) if text.isdigit() else text

#Human sorting
def alphaNum_Key(text):
    return [ alphaNum(c) for c in re.split('(\d+)', text) ]

【问题讨论】:

    标签: python string sorting file-io


    【解决方案1】:

    您可以使用re 执行此操作。

    import re
    x="Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002"
    print sorted(x.split(","),key= lambda k:int(re.findall("(?<=_g)\d+$",k)[0]))
    

    输出:[' Test DATA_g001', ' Test DATA_g002', ' Test DATA_g003', 'Test DATA_g004']

    【讨论】:

    • 排序功能工作正常。但是我在排序“g001”时遇到了问题基本上如何在没有字符串“Test DATA_”的情况下对数据进行排序?
    • @Aurora_Titanium (x.replace('TestData', '') for x in xs
    • @Aurora_Titanium 我在g_ 之后的末尾基于键integers 进行了排序
    • 对不起!我完全忘记了。我检查了我的旧项目,发现我使用了你的解决方案:) python 社区比 C 或 Java 社区好得多。他们对所有内容都投了反对票!
    【解决方案2】:

    检索所有以g开头的字符串,然后用sorted对列表进行排序

    >>> s = "Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002, "
    >>> sorted(re.findall(r'g\d+$', s))
    ['g001', 'g002', 'g003', 'g004']
    

    另一种方法是只使用内置方法:

    >>> l = [x.split('_')[1] for x in s.split(', ') if x]
    >>> l
    ['g004', 'g003', 'g001', 'g002']
    >>> l.sort()
    >>> l
    ['g001', 'g002', 'g003', 'g004']
    

    【讨论】:

    • 非常好的解决方案。优雅干净。
    【解决方案3】:

    是的,你可以。您可以按每个测试子字符串中的最后 3 位数字进行排序:

    # The string to be sorted by digits
    s = "Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002"
    
    # Create a list by splitting at commas, sort the last 3 characters of each element in the list as `ints`.
    l = sorted(s.split(','), key = lambda x: int(x[-3:]))
    
    print l
    # [' Test DATA_g001', ' Test DATA_g002', ' Test DATA_g003', 'Test DATA_g004']
    

    如果l 的元素对你很重要,你会想要修剪它,但这适用于所有以 3 位数字结尾的 Tests。

    如果你不想要Test DATA_,你可以这样做:

    # The string to be sorted by digits
    s = "Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002"
    
    # Create a list by taking the last 4 characters of sorted strings with key as last 3 characters of each element in the list as `int`s.
    l = sorted((x[-4:] for x in s.split(',')), key = lambda x: int(x[-3:]))
    
    print l
    # ['g001', 'g002', 'g003', 'g004']
    

    如果您的数据格式正确(即,g 后跟 3 位数字),这将非常有效。否则,请使用任何其他已发布答案的正则表达式。


    另一种选择是在阅读时将字符串推入PriorityQueue

    test.py

    from Queue import PriorityQueue
    
    q = PriorityQueue()
    
    with open("example.txt") as f:
      # For each line in the file
      for line in f:
        # Create a list from the stripped, split-at-comma string
        for s in line.strip().split(','):
          # Push the last four characters of each element in the list into the pq
          q.put(s[-4:])
    
    while not q.empty():
      print q.get()
    

    使用 PQ 的好处是它会按排序顺序添加它们,这减轻了您的负担,并且在线性时间内完成。

    example.txt

    Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002
    

    还有输出:

    13:25 $ python test.py 
    g001
    g002
    g003
    g004
    

    【讨论】:

    • 感谢您使用对re 进行切片来获取如此简单且外观正常的数据。我认为它使答案以及 OP 缺少的内容更加清晰。
    【解决方案4】:

    听起来你想要“自然排序”。以下是从 https://stackoverflow.com/a/4836734/3019689 复制的,可能会这样做。

    import re
    
    def natural_sort(l): 
        convert = lambda text: int(text) if text.isdigit() else text.lower() 
        alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
        return sorted(l, key = alphanum_key)
    

    但是,您一直说要“不使用Test DATA_”进行排序,这表明您并没有讲述整个故事。如果真的是Test DATA_ every 时间,它不会影响排序:有或没有它的排序;没关系。我敢打赌你真的很担心这个字符串前缀实际上因文件名而异,你想完全忽略它,只关注数字部分。如果是这种情况,您可以将上述列表中的else None 替换为else text.lower()

    【讨论】:

      【解决方案5】:
      import re
      
      def natural_sort(l): 
          convert = lambda text: int(text) if text.isdigit() else text.lower() 
          alphanum_key = lambda key: [ convert(c) for c in re.split('(\d+)', key) ] 
          return sorted(l, key = alphanum_key)
      

      这段代码 sn-p 应该可以正常工作。这种排序称为自然排序,通常用在字母数字的情况下。

      【讨论】:

        猜你喜欢
        • 2021-08-15
        • 2020-09-25
        • 2021-11-07
        • 1970-01-01
        • 1970-01-01
        • 2012-06-24
        • 1970-01-01
        • 1970-01-01
        • 2013-01-14
        相关资源
        最近更新 更多