-1

How do I find the most frequent number over a range of numbers in Bash?

For example:

#!/bin/bash

frequent=0

analog=(889 890 884 880 889 889 884 885 890 890)

for i in ${analog[@]}; do
    # what to do whit this $i ?
done

Since the result is 2 which is 3x 889 and 3x 890, i prefer the result should be 890 (highest) instead 889.

tripleee
  • 175,061
  • 34
  • 275
  • 318
inMILD
  • 168
  • 2
  • 12
  • Do you mean highest valued number (max) or the highest frequency (mode)? – learnerer Jan 07 '19 at 05:46
  • @learnerer not max, but most frequent number. And pick the highest if found double. In the example 889 and 890 is same showed 3x. – inMILD Jan 07 '19 at 05:49

2 Answers2

1

The simplest way is to use an Associative Array and the post-increment operator to increment a count of each number in your analog indexed array, e.g.

#!/bin/bash

analog=(889 890 884 880 889 889 884 885 890 890)
declare -A frequent

for i in ${analog[@]}; do
    ((frequent[$i]++))
done

for i in "${!frequent[@]}"; do
    printf "%s\t%s\n" "$i ==> ${frequent[$i]}"
done

Example Use/Output

$ bash ~/scr/array/freqarray.sh
880 ==> 1
884 ==> 2
885 ==> 1
889 ==> 3
890 ==> 3

You can simply keep a max count as you iterate the associative array and output the key associated with the max frequent value (you have to determine how you handle the ties, e.g. 889, 890 are both 3.)

Identifying the values with the maximum occurrences in analog, you could add maxkey and maxval variables as you loop over the occurrences and then a final loop similar to:

declare -i maxkey=0 maxval=0
for i in "${!frequent[@]}"; do
    printf "%s\t%s\n" "$i ==> ${frequent[$i]}"
    if (( ${frequent[$i]} > maxval )); then
        maxval=${frequent[$i]}
        maxkey=$i
    fi
done

printf "\nmaximum occurences in analog:\n\n"
for i in "${!frequent[@]}"; do
    if (( ${frequent[$i]} == maxval)); then
        printf "%s\t%s\n" "$i ==> ${frequent[$i]}"
    fi
done

Which would then produce the following output:

Example Use/Output

$ bash ~/scr/array/freqarray.sh
880 ==> 1
884 ==> 2
885 ==> 1
889 ==> 3
890 ==> 3

maximum occurences in analog:

889 ==> 3
890 ==> 3

Per Your Edit to Find Highest Value with Maximum Occurrence

To find the highest value with the maximum occurrence, you can simply add an additional check in your second loop and set the maxkey value to the highest value in frequent that has the maxval. For example you can rearrange your final loop and add the output as follows:

printf "\nmaximum occurences in analog:\n\n"
for i in "${!frequent[@]}"; do
    if (( ${frequent[$i]} == maxval)); then
        printf "%s\t%s\n" "$i ==> ${frequent[$i]}"
        (( i > maxkey)) && maxkey=i
    fi
done

printf "\nhighest value with maximum occurrence:\n\n"
printf "%d\n" $maxkey

Example Use/Output

$ bash ~/scr/array/freqarray.sh
880 ==> 1
884 ==> 2
885 ==> 1
889 ==> 3
890 ==> 3

maximum occurences in analog:

889 ==> 3
890 ==> 3

highest value with maximum occurrence:

890
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • Thank you this is so fast, and that is sad to have -1 in my question. BTW, how can we get the highes? Im still new in bash. – inMILD Jan 07 '19 at 06:11
  • 1
    If you just care about finding the first number that satisfies the maximum occurrence, you could use `printf "\nmax is %d (%d occurrances)\n" $maxkey ${frequent[$maxkey]}` – David C. Rankin Jan 07 '19 at 06:14
  • Sorry, i misunderstood. There is no maximum occurrence. Just find the highest value. 890 instead of 889. – inMILD Jan 07 '19 at 06:24
  • Ok, that makes it much, much easier. Just `declare -i max=0; for i in ${analog[@]}; do (( i > max )) && max=$i; done; echo "max: $max"`. Or, if you wanted to use a utility like `sort`, then `printf "%s\n" ${analog[@]} | sort -n | tail -n1` – David C. Rankin Jan 07 '19 at 06:27
0

A similar question was asked here, though the solution by PSkocik finds the minimum, instead of the maximum in the case of a tie. A simple inequality flip from if(what>$1) to if(what< $1) fixes that.

rohanphadte
  • 978
  • 6
  • 19
  • Yeah before i cannot found in stackoverflow, but now im still reading same solution as your link. And still trying to figure how to find highest. Thank you anyway. Prefer rici's answer – inMILD Jan 07 '19 at 06:00