2016-03-27 10 views
0

Ich muss den Mittelwert der in einer Zeichenfolge gespeicherten Werte finden. Ich muss dies in bash ohne zusätzliche temporäre Dateien implementieren und ich kann nicht verwenden Sie awk.Erhalte den Median aus der Wertzeichenfolge

Ich habe diese Zeichenfolge in $string gespeichert:

85 13 4 45 1111 89 87 66 1 5 2 51 13 66 98 50 20 14 18 16 31 21 5175 12 

Erstens, ich brauche diese Werte so sortieren:

1 2 4 5 12 13 13 14 16 18 20 21 31 45 50 51 66 66 85 87 89 98 1111 5175 

Und dann brauche ich Median dieser Werte finden

(21+31)/2 = 26 

Wie kann ich das erreichen? Gibt es in bash einen effizienten Weg oder Befehl?

Meine Idee:

Werte zu sortieren, ich sort verwenden könnte, aber ich bin nicht sicher, wie es zu zwingen Werte von String zu sortieren, weil es mit der Datei ist.

Ich habe keine Ahnung, wie man Median erreichen kann, also würde ich einen kleinen Hinweis zumindest schätzen.

Antwort

1

Um die Zahlen aus der Zeichenfolge in ein sortiertes Array zu erhalten, können Sie sie in einer separaten Zeile drucken kann jeder, Rohr sort -n und dann ein Array lesen in mit mapfile:

string='85 13 4 45 1111 89 87 66 1 5 2 51 13 66 98 50 20 14 18 16 31 21 5175 12' 
mapfile -t arr < <(for num in $string; do echo "$num"; done | sort -n) 

Die -t Option entfernt Zeilenumbrüche von jedem Wert. Beachten Sie, dass Sie nicht können Pipe zu mapfile, denn das wäre in einer Subshell und arr würde danach leer sein.

Es ist normalerweise eine gute Idee, Ihre Variablen zu zitieren, aber in diesem Fall verlassen wir uns auf das Teilen von Wörtern und müssen $string nicht zitieren.

nun für den Median, gibt es zwei Möglichkeiten:

  • Es gibt eine ungerade Anzahl von Array-Elementen und wir wollen nur den Wert des mittleren Elements.
  • Es gibt eine gerade Anzahl von Array-Elementen, und wir wollen den Mittelwert der zwei mittleren Elemente.

Die Anzahl der Array-Elemente ist ${#arr[@]}, so können wir das prüfen und dann entscheiden, was zu tun ist:

auf Integer-Arithmetik
nel=${#arr[@]} 
if ((nel % 2 == 1)); then  # Odd number of elements 
    val="${arr[ $((nel/2)) ]}" 
else       # Even number of elements 
    val="$(((arr[$((nel/2))] + arr[$((nel/2-1))])/2))" 
fi 
printf "%d\n" "$val" 

Dies beruht: Wenn wir eine ungerade Anzahl von Elementen haben, sagen drei , der Index des Medians ist 1 –, die wir von der ganzzahligen Teilung von drei durch zwei bekommen. Für eine gerade Anzahl von Elementen, sagen wir vier, wollen wir die Elemente bei Index 1 und 2, die wir erhalten, indem wir für den höheren Index jeweils vier mal zwei dividieren und für den niedrigeren Index eins davon abziehen.

Wenn sich die beiden Elemente nicht zu einer geraden Zahl addieren, wird das Ergebnis abgerundet.Wenn das nicht gut genug ist, können wir entweder überprüfen, ob die Zahl ungerade ist, und manuell .5 zum Ergebnis hinzufügen, oder wir können bc verwenden, um die Berechnung durchzuführen. Überlegen Sie:

$ echo $((11/2)) 
5 
$ bc <<< 'scale=1; 11/2' 
5.5 
1

können Sie Befehle wie folgt aus:

str="85 13 4 45 1111 89 87 66 1 5 2 51 13 66 98 50 20 14 18 16 31 21 5175 12" 
count=$(echo $str | wc -w) 
arr=($(echo $str | tr " " "\n" | sort -n)) 
#echo ${arr[*]} 

if [[ $(($count % 2)) == 0 ]]; then 
    # even element count, get the elements around the middle 
    f1=${arr[ $(((count - 1) /2)) ]} 
    f2=${arr[ $(((count + 1) /2)) ]} 
    #echo "f1=$f1, f2=$f2" 
    echo $((($f1 + f2)/2)) 
else 
    # odd element count 
    echo ${arr[ $(($count/2))]} 
fi 
Verwandte Themen