2014-04-21 48 views
-6

我有一個看起來像以下數據:升序排序字段,刪除第一和最後一個數字

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 
.... 
.... 

任何幫助將不勝感激!

+7

您可以編寫一個軟件程序來爲你做的。然後運行該程序。 – juanchopanza

+1

很酷的數據。它是一個文本文件嗎?一個CSV?你已經讀過了嗎?到目前爲止,你有什麼? – thegrinner

+0

它是一個文本文件。我仍然試圖找出如何提升單元格內的數據。我不知道如何甚至搜索這個功能。 – user3546860

回答

0

的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 
+1

您還可以使用:'f1 = sorted(f1.split(','),key = int)[1:-1]' –

+0

如果您有你的「索引」和你可以使用的正則表達式之間的空間數量不確定:re.split('\ s \ W +',line) –

+0

@IanLaird:'str.split'取決於任務:''blue \ t \ r 1,2 \ n'.split()'給出'['blue','1,2']'。 –

2

在這裏你去:

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如果我記得正確的,你需要gnu awk由於asort

它是如何工作的:

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 
+0

您可以使用'split'或'asort'的返回值並在'for loop'中使用它,而不是使用'length(a)'函數。同樣在'ternary op'中,你可以做'?'\ n「:」,「'並跳過'print」「'。 –

+1

@JS웃嗨,感謝您的信息,文章已更新。剛剛修改了一篇文章,我發現使用谷歌:)。 PS我認爲'RS'優於''\ n「' – Jotne

0

完整的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) 
+0

如果在'sorted'上使用'key = int'參數,則不需要將'str'轉換爲'int'到'str'。另外,如果你真的想全力以赴,捕獲正則表達式中的空白,然後在輸出中重用它。 –

+0

感謝您的正則表達式的建議。映射到int仍然是必需的,因爲它將剝離輸入數據中的訓練'\ n'。但我認爲,你給我的分裂認識否定了正則表達式的整體需求。 –

+0

'str.split(d)'與'd.split()'相同。 –

1

嗯,這裏是用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 
+0

好的! (請注意,您可以在'splice'命令中省略'@ {..}',只需使用'splice [sort {$ a <=> $ b} @F [1 .. $#F]],1,$# F#2。) –

+0

謝謝@HåkonHægland,'splice'的第一個參數應該是一個數組,因此它不會接受匿名數組,除非您將其解除引用。 –

+0

其實我認爲方括號產生一個數組引用,請參閱:http://perldoc.perl.org/perlref.html ..這就是爲什麼你不需要取消引用它.. –

相關問題