Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash unix按其关联的最大值对组进行排序?_Bash_Sorting_Unix_Grouping_Gnu Coreutils - Fatal编程技术网

Bash unix按其关联的最大值对组进行排序?

Bash unix按其关联的最大值对组进行排序?,bash,sorting,unix,grouping,gnu-coreutils,Bash,Sorting,Unix,Grouping,Gnu Coreutils,假设我有一个输入文件49142202.txt: A 5 B 6 C 3 A 4 B 2 C 1 是否可以按第2列中的值对第1列中的组进行排序?所需的输出如下所示: B 6 <-- B group at the top, because 6 is larger than 5 and 3 B 2 <-- 2 less than 6 A 5 <-- A group in the middle, because 5 is smaller than

假设我有一个输入文件
49142202.txt

A   5
B   6
C   3
A   4
B   2
C   1
是否可以按第2列中的值对第1列中的组进行排序?所需的输出如下所示:

B   6 <-- B group at the top, because 6 is larger than 5 and 3
B   2 <-- 2 less than 6
A   5 <-- A group in the middle, because 5 is smaller than 6 and larger than 3
A   4 <-- 4 less than 5
C   3 <-- C group at the bottom, because 3 is smaller than 6 and 5
C   1 <-- 1 less than 3
按第1列排序的
join
的第二个输入是:

A   5
A   4
B   6
B   2
C   3
C   1
join
的输出为:

A   2   5
A   2   4
B   1   6
B   1   2
C   3   3
C   3   1
然后按列2中的
nl
行号对其进行排序,然后原始输入列1和3保留为
cut


我知道用Python的熊猫(pandas of Python)可以轻松得多,但是有没有更优雅的方法来做到这一点,同时坚持使用诸如、、和?我最好避免使用内存效率低下的
awk
解决方案,但也请分享这些解决方案。谢谢

因此,这并不适用于所有情况,但是如果第一列中的值可以转换为bash变量,那么我们可以使用动态命名的数组来实现这一点,而不是使用一组联接。应该很快

第一个while块读入文件的内容,获取前两个空格分隔的字符串,并将它们放入
col1
col2
中。然后,我们创建一系列名为
ARR_a
ARR_B
的数组,其中
a
B
是第1列中的值(但仅当
$col1
仅包含可以在bash变量名中使用的字符时)。该数组包含与这些第1列值关联的第2列值

我使用你的奇妙排序链来获得我们希望列1的值打印出来的顺序,我们只是循环遍历它们,然后对每个列1数组的值进行排序,并回显列1和列2

dynamc变量位可能很难遵循,但对于第1列中的正确值,它将起作用。同样,如果第1列中有任何字符不能作为bash变量名的一部分,则此解决方案将不起作用

file=./49142202.txt

while read col1 col2 extra
do
  if [[ "$col1" =~ ^[a-zA-Z0-9_]+$ ]]
  then
    eval 'ARR_'${col1}'+=("'${col2}'")'
  else
    echo "Bad character detected in Column 1:  '$col1'"
    exit 1
  fi
done < "$file"

sort -k2nr,2 "$file" | sort --stable -k1,1 -u | sort -k2nr,2 | while read col1 extra
do 
  for col2 in $(eval 'printf "%s\n" "${ARR_'${col1}'[@]}"' | sort -r)
  do
    echo $col1 $col2
  done
done 

如注释中所述,我的解决方案试图减少
管道
、不必要的
cat
命令的数量,尤其是管道
排序
操作的数量,因为排序是一项复杂/耗时的操作

join -t$'\t' -1 2 -2 1 \
 <(cat 49142202.txt | sort -k2nr,2 | sort --stable -k1,1 -u | sort -k2nr,2 \
  | cut -f1 | nl | tr -d " " | sort -k2,2) \
 <(cat 49142202.txt | sort -k1,1 -k2nr,2) \
| sort --stable -k2n,2 | cut -f1,3
我找到了以下解决方案,
f\u grp\u sort
是输入文件:

for elem in $(sort -k2nr f_grp_sort | awk '!seen[$1]++{print $1}')
do 
   grep $elem <(sort -k2nr f_grp_sort) 
done
解释:

sort-k2nr f_grp_sort
将生成以下输出:

B       6
A       5
A       4
C       3
B       2
C       1
sort-k2nr f_grp_sort | awk'!已看到[$1]+{print$1}'
将生成输出:

B
A
C
awk
只会以相同的顺序生成临时输出第一列的1个唯一元素


然后,$(…)中的元素的
,请执行grep$elem非常感谢@JeffBreadner和@Allan!我提出了另一个解决方案,它与我的第一个解决方案非常相似,但提供了更多的控制,因为它允许更容易地嵌套for循环:

for x in $(sort -k2nr,2 $file | sort --stable -k1,1 -u | sort -k2nr,2 | cut -f1); do
 awk -v x=$x '$1==x' $file | sort -k2nr,2
done

在我有时间评估您的解决方案的时间和内存性能之前,如果我不接受您的任何一个答案,您介意吗?否则我可能会选择@Allan的
awk
解决方案。

顺便说一句,因为你谈论的是性能:
cat 49142202.txt | sort-k2nr,2
是做你认为你正在做的事情的非常糟糕的方式->你根本不需要猫。在两个命令中!!!还要注意,使用许多管道和运行许多进程并不是免费的,您必须考虑进程之间的所有切换成本!最后但并非最不重要的一点是,管道化所有
排序
命令将大大降低长文件的执行速度@艾伦:好点!我同意!嘿,到底什么是对你最好的解决方案?@Allan工作有点忙,我要到下周末才有时间评估。我很高兴接受你的回答。让我知道您喜欢什么。在进行一些测试时,我的解决方案将消除重复项,这可能是您不想要的(与其他解决方案相比,它非常复杂)。由tommy.carstensen和Allan提出的解决方案运行的时间几乎相同。如果你是唯一一个看到或维护代码的人,那么你编写的代码总是更受支持的,但是如果其他人会使用此代码,我建议使用Allan提供的解决方案,因为它在我看来更优雅。谢谢tommy.carstensen写了一个好的有趣的问题:D
B       6
A       5
A       4
C       3
B       2
C       1
B
A
C
$ sort -k2nr f_grp_sort > tmp_sorted_file && for elem in $(awk '!seen[$1]++{print $1}' tmp_sorted_file); do grep $elem tmp_sorted_file; done && rm tmp_sorted_file
for x in $(sort -k2nr,2 $file | sort --stable -k1,1 -u | sort -k2nr,2 | cut -f1); do
 awk -v x=$x '$1==x' $file | sort -k2nr,2
done