【问题标题】:sort a field in ascending order and delete the first and last number [closed]按升序对字段进行排序并删除第一个和最后一个数字[关闭]
【发布时间】:2014-06-05 16:16:55
【问题描述】:

我的数据如下所示:

a     10,5,3,66,50
b     2,10,1,88,5,8,9
c     4,60,10,39,55,22
d     1,604,3,503,235,45,60,7
e     20,59,33,2,6,45,36,34,22

我想对第二列中的数据进行升序排序

a     3,5,10,50,66
b     1,2,5,8,9,10,88
c     4,10,22,39,55,60
....
....

然后从中删除最小值和最大值。像这样:

a     5,10,50
b     2,5,8,9,10
c     10,22,39,55
....
....

任何帮助将不胜感激!

【问题讨论】:

  • 您可以编写一个软件程序来为您执行此操作。然后运行程序。
  • 酷数据。是文本文件吗? CSV?你已经读进去了吗?到目前为止你有什么?
  • 它是一个文本文件。我仍在试图弄清楚如何提升单元格内的数据。我什至不知道如何搜索此功能。

标签: python awk


【解决方案1】:

给你:

awk '{l=split($2,a,",");asort(a);printf "%s\t",$1;for(i=2;i<l;i++) printf "%s"(i==l-1?RS:","),a[i]}' t
a       5,10,50
b       2,5,8,9,10
c       10,22,39,55
d       3,7,45,60,235,503
e       6,20,22,33,34,36,45

PS 如果我没记错的话,由于asort,你需要gnu awk

它是如何工作的:

awk '
    {l=split($2,a,",")                      # Split the data into array "a" and set "l" to length of array
    asort(a)                                # Sort the array "a"
    printf "%s\t",$1                        # Print the first column
    for(i=2;i<l;i++)                        # Run a loop from second element to second last element in array "a"
        printf "%s"(i==l-1?RS:","),a[i]     # Print the element separated by "," except for last element, print a new line
    }'  file                                # Read the file

【讨论】:

  • 您可以使用splitasort 的返回值并在for loop 中使用它,而不是使用length(a) 函数。同样在ternary op 中,您可以执行?"\n":"," 并跳过print ""
  • @JS웃 您好,感谢您提供的信息,帖子已更新。刚刚修改了我使用谷歌找到的帖子:)。 PS我觉得RS"\n"
【解决方案2】:

Python:

with open('the_file.txt', 'r') as fin, open('result.txt', 'w') as fout:
    for line in fin:
        f0, f1 = line.split() 
        fout.write('%s\t%s\n' % (f0, ','.join(sorted(f1.split(','), key=int)[1:-1])))

循环体可以解包为:

        f0, f1 = line.split()           # split fields on whitespace
        items = f1.split(',')           # split second field on commas
        items = sorted(items, key=int)  # or items.sort(key=int) # sorts items as int
        items = items[1:-1]             # get rid of first and last items
        f1 = ','.join(items)            # reassemble field as csv
        line = '%s\t%s\n' % (f0, f1)    # reassemble line
        fout.write(line)                # write it out

【讨论】:

  • 您也可以使用:f1 = sorted(f1.split(','), key=int)[1:-1]
  • 如果您的“索引”和数据之间有未知数量的空格,您可以使用正则表达式,例如:re.split('\s\W+', line)
  • @IanLaird: str.split 完成任务:' blue \t \r 1,2\n'.split() 提供['blue', '1,2']
  • 你说得对,我刚刚意识到我正在传递 str.split(d, ' ')。
【解决方案3】:

完整的python示例。这假设您的数据位于文本文件中。你可以这样称呼它。

./parser.py filename

或者你可以像这样把它放在一起:

echo 'a    3,2,1,4,5' | ./parser.py -

代码:

#!/bin/env python
import argparse
import sys

def splitAndTrim(d):
    line = str.split(d)
    arr = sorted(map(int, line[1].split(',')))
    print("{0}    {1}".format(line[0], ",".join(map(str, arr[1:-1]))))


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('FILE', type=argparse.FileType('r'), default=sys.stdin)
    args = parser.parse_args(sys.argv[1:])
    for line in args.FILE:
        splitAndTrim(line)

【讨论】:

  • 如果在sorted 上使用key=int 参数,则无需从str 转换为intstr。此外,如果您真的想全力以赴,请在正则表达式中捕获空格,然后在输出中重用它。
  • 感谢您的正则表达式建议。仍然需要到 int 的映射,因为它正在剥离输入数据中的训练 '\n'。但我认为你给我的分裂认识在某种程度上否定了对正则表达式的需求。
  • str.split(d)d.split() 相同
【解决方案4】:

嗯,这是使用perl 的替代解决方案:

$ perl -F'\s+|,' -lane '
print $F[0] . "\t" . join "," , splice @{[sort { $a<=>$b } @F[1..$#F]]} , 1, $#F-2' file
a       5,10,50
b       2,5,8,9,10
c       10,22,39,55
d       3,7,45,60,235,503
e       6,20,22,33,34,36,45

或使用较新版本的 perl,您可以删除 @{..} 并说:

perl -F'\s+|,' -lane '
    print $F[0] . "\t" . join "," , splice [sort { $a<=>$b } @F[1..$#F]] , 1, $#F-2
' file

或者只使用子脚本:

perl -F'\s+|,' -lane '
    print $F[0] . "\t" . join "," , ( sort { $a<=>$b }@F[1..$#F] ) [1..$#F-2]
' file

【讨论】:

  • 不错的一个! (注意,splice 命令中的@{ .. } 可以省略,直接使用splice [sort { $a&lt;=&gt;$b } @F[1..$#F]] , 1, $#F-2即可。)
  • 感谢@HåkonHægland,splice 的第一个参数应该是一个数组,因此除非您取消引用它,否则它不会采用匿名数组。
  • 其实我认为方括号产生一个数组引用,见:perldoc.perl.org/perlref.html ..这就是为什么你不需要取消引用它..
  • @HåkonHægland 如果你不输入@{..} - Type of arg 1 to splice must be array (not anonymous list ([]))..,这就是你会得到的错误
  • 可能跟perl的版本有关?这个命令:perl -F'\s+|,' -lane 'print join "," , splice [sort { $a&lt;=&gt;$b } @F[1..$#F]] , 1, $#F-2' file 对我来说很好用。我正在使用 perl 5.14 版。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-18
  • 2015-04-17
  • 2018-08-07
  • 1970-01-01
  • 1970-01-01
  • 2018-07-29
  • 2023-03-21
相关资源
最近更新 更多