1

I have this array:

array=(1 2 3 4 4 3 4 3)

I can get the largest number with:

echo "num: $(printf "%d\n" ${array[@]} | sort -nr | head -n 1)"
#outputs 4

But i want to get all 4's add sum them up, meaning I want it to output 12 (there are 3 occurrences of 4) instead. any ideas?

4 Answers 4

5
dc <<<"$(printf '%d\n' "${array[@]}" | sort -n | uniq -c  | tail -n 1) * p"
  1. sort to get max value at end
  2. uniq -c to get only unique values, with a count of how many times they appear
  3. tail to get only the last line (with the max value and its count)
  4. dc to multiply the value by the count

I picked dc for the multiplication step because it's RPN, so you don't have to split up the uniq -c output and insert anything in the middle of it - just add stuff to the end.

Sign up to request clarification or add additional context in comments.

Comments

3

Using awk:

$ printf "%d\n" "${array[@]}" | sort -nr | awk 'NR>1 && p!=$0{print x;exit;}{x+=$0;p=$0;}'
12

Using sort, the numbers are sorted(-n) in reverse(-r) order, and the awk keeps summing the numbers till it finds a number which is different from the previous one.

1 Comment

+1. Doh, of course; I thought you'd need two loops, but since it's already reversed sorted it becomes almost trivial :)
2

You can do this with awk:

awk -v RS=" " '{sum[$0]+=$0; if($0>max) max=$0} END{print sum[max]}' <<<"${array[@]}"

Setting RS (record separator) to space allows you to read your array entries as separate records.

sum[$0]+=$0; means sum is a map of cumulative sums for each input value; if($0>max) max=$0 calculates the max number seen so far; END{print sum[max]} prints the sum for the larges number seen at the end.

<<<"${array[@]}" is a here-document that allows you to feed a string (in this case all elements of the array) as stdin into awk.

This way there is no piping or looping involved - a single command does all the work.

1 Comment

+1, Nice use of awk's RS. You can save a few chars by moving the if condition to a new branch: {sum[$0]+=$0} $0>max {max=$0}
-1

Using only bash:

echo $((${array// /+}))

Replace all spaces with plus, and evaluate using double-parentheses expression.

2 Comments

This does not answer the question, even if I find your approach cool. Plus it does not work for me. However echo $(printf "%d+" ${speeds[@]})0 | bc did the trick.
@Titou I got it to work with echo $((${array[@]/%/+}0)). Super-cutesy, though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.