Ho un nome di file numeri, contiene semplicemente numeri casuali
1 2 3
7 5 9
2 2 9
5 4 5
7 2 6
Devo creare uno script che trovi la mediana per ogni riga, e qui c'è il mio codice:
while read -a row
do
for i in "${row[@]}"
do
length=`expr ${#row[@]} % 2`
if [ $length -ne 0 ] ; then
mid=`expr ${#row[@]} / 2`
echo ${row[middle]}
elif [ $length -eq 0 ] ; then
val1=`expr ${#row[@]} / 2`
val2=`expr (${$row[@]} / 2) + 1`
mid=`expr ($val1 + $val2) / 2`
echo $mid
done | sort -n
done < numbers
Tuttavia questo non funziona, mostra invece un errore.Che errore ho fatto in questo codice? Inoltre non riesco ancora a capire dove sia il modo corretto di posizionare il sort -n
dal momento che deve essere ordinato prima di calcolare la mediana, giusto?
risposte:
1 per risposta № 1Bash può solo fare aritmetica intera, è necessario uno strumento come bc
calcolare la media:
#!/bin/bash
while read -a n ; do
n=($(IFS=$"n" ; echo "${n[*]}" | sort -n))
len=${#n[@]}
if (( len % 2 )) ; then
echo ${n[ len / 2 ]}
else
bc -l <<< "scale=1; (${n[ len / 2 - 1 ]} + ${n[ len / 2 ]}) / 2"
fi
done
Probabilmente avrei raggiunto un linguaggio di livello superiore, ad esempio Perl:
#!/usr/bin/perl
use warnings;
use strict;
while (<>) {
my @n = sort { $a <=> $b } split;
print @n % 2 ? $n[ @n / 2 ]
: ($n[ @n / 2 - 1 ] + $n[ @n / 2 ]) / 2,
"n";
}
0 per risposta № 2
Dovevo solo farlo, per il gusto di farlo.
Notate che non uso un if
ma frazioni di indici.
awk "{
split($0,a) # create array a from input line
asort(a,b) # sort array into array b (gnu awk specific)
# add twice the median, or around the median and divide by 2
print ( b[int(NF/2+0.7)] + b[int(NF/2+1.2)] )/2
}" numbers
Accorciato (67 caratteri):
awk "{split($0,a);asort(a,b);print(b[int(NF/2+0.7)]+b[int(NF/2+1.2)])/2}" numbers
66 golfs chars :-)
awk "{split($0,a);asort(a,b);$0=(b[int(NF/2+0.7)]+b[int(NF/2+1.2)])/2}1" numbers