2016-03-27 20 views
0

Bir dize kaydedilmiş medyan değerleri bulmam gerekiyor. Bu ek bir geçici dosya olmadan bash bunu uygulamak zorundayım ve ben awk kullanamazsınız.Değer dizesinden medyan alın

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

Birincisi, böyle bu değerleri sıralamak gerekir:

ben bu dize $string kaydedilmiş olması

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

Sonra bu değerlerin ortancasını bulmalıyız

(21+31)/2 = 26 

Bunu nasıl başarabiliriz? Bash'da herhangi bir etkili yol veya komut var mı?

Benim fikrim:

Ben sort kullanabilirsiniz, değerlerini sıralamak için, ancak DOSYASINI kullanarak çünkü ben, dize değerleri sıralamak için zorlamak nasıl emin değilim.

olsa medyan nasıl ulaşılacağını hiçbir fikrim yok, bu yüzden en azından küçük ipucu takdir ediyorum.

cevap

1

sıralanmış bir diziye dize numaraları almak için, daha sonra sort -n için, ayrı bir satıra her biri üzerinde boru bunları yazdırabilir ve bir diziye okunan mapfile ile:

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) 

-t seçenek her değerden yeni satır kaldırır. Eğer o bir kabuktaki mapfile için boru olacaktır çünkü ve arr sonradan boş olacağını dikkat edin.

Genellikle sizin değişkenleri alıntı için iyi bir fikir olduğunu, ancak bu durumda biz sözcük Siil itimat ve $string alıntı etmemelidir.

  • Orada dizi öğelerinin bir tek sayı olduğu ve sadece orta öğesinin değerini istiyorum:

    Şimdi, median, iki seçenek vardır.

  • Çok sayıda dizi öğesi vardır ve iki orta öğenin ortalamasını istiyoruz.

dizi öğelerinin sayısı ${#arr[@]}, bu yüzden ne yapacağımıza karar daha sonra kontrol edebilir:

Bu integral işlemlerinde dayanır
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" 

: Biz unsurların tek sayıda varsa, üç demek , medyanın indeksi, ikiye bölünerek tamsayı bölmesinden aldığımız 1 –'dur. Dörde eşit sayıda eleman için, diyelim ki, indeks 1 ve 2'deki elemanları istiyoruz, ki bu daha yüksek endeks için ikiye bölünerek ve alt indeksten ondan bir tane çıkararak elde ederiz.

iki element bir çift sayıya kadar ekleyin yoksa

, sonuç aşağı yuvarlanır.Bu yeterince iyi değilse, sayı tek olup olmadığını kontrol edebilir ve el ile sonucu .5 ekleyebiliriz veya hesaplama yapmak için bc'u kullanabiliriz. Şunları düşünün:

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

Aşağıdaki gibi komutları kullanabilirsiniz:

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