Find second largest value in array
Clash Royale CLAN TAG#URR8PPP
I have an array like this:
array=(1 2 7 6)
and would like to search for the second largest value, with the output being
secondGreatest=6
Is there any way to do this in bash?
bash bash-array
add a comment |
I have an array like this:
array=(1 2 7 6)
and would like to search for the second largest value, with the output being
secondGreatest=6
Is there any way to do this in bash?
bash bash-array
3
What ifarray=(1 2 7 6 7)
? What is the 2nd largest value, 6 or 7?
– glenn jackman
Jan 23 at 15:38
add a comment |
I have an array like this:
array=(1 2 7 6)
and would like to search for the second largest value, with the output being
secondGreatest=6
Is there any way to do this in bash?
bash bash-array
I have an array like this:
array=(1 2 7 6)
and would like to search for the second largest value, with the output being
secondGreatest=6
Is there any way to do this in bash?
bash bash-array
bash bash-array
asked Jan 23 at 13:05
ToasterFrogsToasterFrogs
443
443
3
What ifarray=(1 2 7 6 7)
? What is the 2nd largest value, 6 or 7?
– glenn jackman
Jan 23 at 15:38
add a comment |
3
What ifarray=(1 2 7 6 7)
? What is the 2nd largest value, 6 or 7?
– glenn jackman
Jan 23 at 15:38
3
3
What if
array=(1 2 7 6 7)
? What is the 2nd largest value, 6 or 7?– glenn jackman
Jan 23 at 15:38
What if
array=(1 2 7 6 7)
? What is the 2nd largest value, 6 or 7?– glenn jackman
Jan 23 at 15:38
add a comment |
3 Answers
3
active
oldest
votes
printf '%sn' "$array[@]" | sort -n | tail -2 | head -1
Print each value of the array on it's own line, sort it, get the last 2 values, remove the last value
secondGreatest=$(printf '%sn' "$array[@]" | sort -n | tail -2 | head -1)
Set that value to the secondGreatest
variable.
Glenn Jackman had an excellent point about duplicate numbers that I didn't consider. If you only care about unique values you can use the -u
flag of sort:
secondGreatest=$(printf '%sn' "$array[@]" | sort -nu | tail -2 | head -1)
5
You could save one pipe if you reverse sort, so that the answer is always in second place e.g.printf '%sn' "$array[@]" | sort -rn | awk NR==2
(likelyhead
+tail
is more efficient though) or (at least with GNU Coreutils, which support the null delimiters)printf '%s' "$array[@]" | sort -rzn | cut -d '' -f2
– steeldriver
Jan 23 at 14:03
add a comment |
A bash-specific loop through the array could do it; you have to keep track of the largest and second-largest. The only other tricky part is to be careful about initializing those values; the largest value is initialized to the first element; the second-largest value is initialized the first time we see a value that's smaller than the largest value. Subsequently for the second-largest value, we only update it if it's strictly less than the current largest value:
#!/bin/bash
array=(7 7 6 2 1)
if [ "$#array[@]" -lt 2 ]
then
echo Incoming array is not large enough >&2
exit 1
fi
largest=$array[0]
secondGreatest='unset'
for((i=1; i < $#array[@]; i++))
do
if [[ $array[i] > $largest ]]
then
secondGreatest=$largest
largest=$array[i]
elif (( $array[i] != $largest )) && [[ "$secondGreatest" = "unset" ]]
then
secondGreatest=$array[i]
fi
done
echo "secondGreatest = $secondGreatest"
It's still slower than calling out to sort
, but it has the added benefit of picking the strictly-smaller second-largest value in the face of multiple high values (such as 7
and 7
above).
add a comment |
It's a good job for dc :
array=(1 2 7 6)
echo $array[*] | dc -f - -e '
[lasbdsa]sB
[dla!>Bsc1z>A]sA
lAx
[secondGreatest=]nlbp'
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f496213%2ffind-second-largest-value-in-array%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
printf '%sn' "$array[@]" | sort -n | tail -2 | head -1
Print each value of the array on it's own line, sort it, get the last 2 values, remove the last value
secondGreatest=$(printf '%sn' "$array[@]" | sort -n | tail -2 | head -1)
Set that value to the secondGreatest
variable.
Glenn Jackman had an excellent point about duplicate numbers that I didn't consider. If you only care about unique values you can use the -u
flag of sort:
secondGreatest=$(printf '%sn' "$array[@]" | sort -nu | tail -2 | head -1)
5
You could save one pipe if you reverse sort, so that the answer is always in second place e.g.printf '%sn' "$array[@]" | sort -rn | awk NR==2
(likelyhead
+tail
is more efficient though) or (at least with GNU Coreutils, which support the null delimiters)printf '%s' "$array[@]" | sort -rzn | cut -d '' -f2
– steeldriver
Jan 23 at 14:03
add a comment |
printf '%sn' "$array[@]" | sort -n | tail -2 | head -1
Print each value of the array on it's own line, sort it, get the last 2 values, remove the last value
secondGreatest=$(printf '%sn' "$array[@]" | sort -n | tail -2 | head -1)
Set that value to the secondGreatest
variable.
Glenn Jackman had an excellent point about duplicate numbers that I didn't consider. If you only care about unique values you can use the -u
flag of sort:
secondGreatest=$(printf '%sn' "$array[@]" | sort -nu | tail -2 | head -1)
5
You could save one pipe if you reverse sort, so that the answer is always in second place e.g.printf '%sn' "$array[@]" | sort -rn | awk NR==2
(likelyhead
+tail
is more efficient though) or (at least with GNU Coreutils, which support the null delimiters)printf '%s' "$array[@]" | sort -rzn | cut -d '' -f2
– steeldriver
Jan 23 at 14:03
add a comment |
printf '%sn' "$array[@]" | sort -n | tail -2 | head -1
Print each value of the array on it's own line, sort it, get the last 2 values, remove the last value
secondGreatest=$(printf '%sn' "$array[@]" | sort -n | tail -2 | head -1)
Set that value to the secondGreatest
variable.
Glenn Jackman had an excellent point about duplicate numbers that I didn't consider. If you only care about unique values you can use the -u
flag of sort:
secondGreatest=$(printf '%sn' "$array[@]" | sort -nu | tail -2 | head -1)
printf '%sn' "$array[@]" | sort -n | tail -2 | head -1
Print each value of the array on it's own line, sort it, get the last 2 values, remove the last value
secondGreatest=$(printf '%sn' "$array[@]" | sort -n | tail -2 | head -1)
Set that value to the secondGreatest
variable.
Glenn Jackman had an excellent point about duplicate numbers that I didn't consider. If you only care about unique values you can use the -u
flag of sort:
secondGreatest=$(printf '%sn' "$array[@]" | sort -nu | tail -2 | head -1)
edited Jan 23 at 20:37
answered Jan 23 at 13:16
Jesse_bJesse_b
12.7k23067
12.7k23067
5
You could save one pipe if you reverse sort, so that the answer is always in second place e.g.printf '%sn' "$array[@]" | sort -rn | awk NR==2
(likelyhead
+tail
is more efficient though) or (at least with GNU Coreutils, which support the null delimiters)printf '%s' "$array[@]" | sort -rzn | cut -d '' -f2
– steeldriver
Jan 23 at 14:03
add a comment |
5
You could save one pipe if you reverse sort, so that the answer is always in second place e.g.printf '%sn' "$array[@]" | sort -rn | awk NR==2
(likelyhead
+tail
is more efficient though) or (at least with GNU Coreutils, which support the null delimiters)printf '%s' "$array[@]" | sort -rzn | cut -d '' -f2
– steeldriver
Jan 23 at 14:03
5
5
You could save one pipe if you reverse sort, so that the answer is always in second place e.g.
printf '%sn' "$array[@]" | sort -rn | awk NR==2
(likely head
+ tail
is more efficient though) or (at least with GNU Coreutils, which support the null delimiters) printf '%s' "$array[@]" | sort -rzn | cut -d '' -f2
– steeldriver
Jan 23 at 14:03
You could save one pipe if you reverse sort, so that the answer is always in second place e.g.
printf '%sn' "$array[@]" | sort -rn | awk NR==2
(likely head
+ tail
is more efficient though) or (at least with GNU Coreutils, which support the null delimiters) printf '%s' "$array[@]" | sort -rzn | cut -d '' -f2
– steeldriver
Jan 23 at 14:03
add a comment |
A bash-specific loop through the array could do it; you have to keep track of the largest and second-largest. The only other tricky part is to be careful about initializing those values; the largest value is initialized to the first element; the second-largest value is initialized the first time we see a value that's smaller than the largest value. Subsequently for the second-largest value, we only update it if it's strictly less than the current largest value:
#!/bin/bash
array=(7 7 6 2 1)
if [ "$#array[@]" -lt 2 ]
then
echo Incoming array is not large enough >&2
exit 1
fi
largest=$array[0]
secondGreatest='unset'
for((i=1; i < $#array[@]; i++))
do
if [[ $array[i] > $largest ]]
then
secondGreatest=$largest
largest=$array[i]
elif (( $array[i] != $largest )) && [[ "$secondGreatest" = "unset" ]]
then
secondGreatest=$array[i]
fi
done
echo "secondGreatest = $secondGreatest"
It's still slower than calling out to sort
, but it has the added benefit of picking the strictly-smaller second-largest value in the face of multiple high values (such as 7
and 7
above).
add a comment |
A bash-specific loop through the array could do it; you have to keep track of the largest and second-largest. The only other tricky part is to be careful about initializing those values; the largest value is initialized to the first element; the second-largest value is initialized the first time we see a value that's smaller than the largest value. Subsequently for the second-largest value, we only update it if it's strictly less than the current largest value:
#!/bin/bash
array=(7 7 6 2 1)
if [ "$#array[@]" -lt 2 ]
then
echo Incoming array is not large enough >&2
exit 1
fi
largest=$array[0]
secondGreatest='unset'
for((i=1; i < $#array[@]; i++))
do
if [[ $array[i] > $largest ]]
then
secondGreatest=$largest
largest=$array[i]
elif (( $array[i] != $largest )) && [[ "$secondGreatest" = "unset" ]]
then
secondGreatest=$array[i]
fi
done
echo "secondGreatest = $secondGreatest"
It's still slower than calling out to sort
, but it has the added benefit of picking the strictly-smaller second-largest value in the face of multiple high values (such as 7
and 7
above).
add a comment |
A bash-specific loop through the array could do it; you have to keep track of the largest and second-largest. The only other tricky part is to be careful about initializing those values; the largest value is initialized to the first element; the second-largest value is initialized the first time we see a value that's smaller than the largest value. Subsequently for the second-largest value, we only update it if it's strictly less than the current largest value:
#!/bin/bash
array=(7 7 6 2 1)
if [ "$#array[@]" -lt 2 ]
then
echo Incoming array is not large enough >&2
exit 1
fi
largest=$array[0]
secondGreatest='unset'
for((i=1; i < $#array[@]; i++))
do
if [[ $array[i] > $largest ]]
then
secondGreatest=$largest
largest=$array[i]
elif (( $array[i] != $largest )) && [[ "$secondGreatest" = "unset" ]]
then
secondGreatest=$array[i]
fi
done
echo "secondGreatest = $secondGreatest"
It's still slower than calling out to sort
, but it has the added benefit of picking the strictly-smaller second-largest value in the face of multiple high values (such as 7
and 7
above).
A bash-specific loop through the array could do it; you have to keep track of the largest and second-largest. The only other tricky part is to be careful about initializing those values; the largest value is initialized to the first element; the second-largest value is initialized the first time we see a value that's smaller than the largest value. Subsequently for the second-largest value, we only update it if it's strictly less than the current largest value:
#!/bin/bash
array=(7 7 6 2 1)
if [ "$#array[@]" -lt 2 ]
then
echo Incoming array is not large enough >&2
exit 1
fi
largest=$array[0]
secondGreatest='unset'
for((i=1; i < $#array[@]; i++))
do
if [[ $array[i] > $largest ]]
then
secondGreatest=$largest
largest=$array[i]
elif (( $array[i] != $largest )) && [[ "$secondGreatest" = "unset" ]]
then
secondGreatest=$array[i]
fi
done
echo "secondGreatest = $secondGreatest"
It's still slower than calling out to sort
, but it has the added benefit of picking the strictly-smaller second-largest value in the face of multiple high values (such as 7
and 7
above).
answered Jan 23 at 14:38
Jeff SchallerJeff Schaller
41.2k1056131
41.2k1056131
add a comment |
add a comment |
It's a good job for dc :
array=(1 2 7 6)
echo $array[*] | dc -f - -e '
[lasbdsa]sB
[dla!>Bsc1z>A]sA
lAx
[secondGreatest=]nlbp'
add a comment |
It's a good job for dc :
array=(1 2 7 6)
echo $array[*] | dc -f - -e '
[lasbdsa]sB
[dla!>Bsc1z>A]sA
lAx
[secondGreatest=]nlbp'
add a comment |
It's a good job for dc :
array=(1 2 7 6)
echo $array[*] | dc -f - -e '
[lasbdsa]sB
[dla!>Bsc1z>A]sA
lAx
[secondGreatest=]nlbp'
It's a good job for dc :
array=(1 2 7 6)
echo $array[*] | dc -f - -e '
[lasbdsa]sB
[dla!>Bsc1z>A]sA
lAx
[secondGreatest=]nlbp'
answered Jan 23 at 19:32
ctac_ctac_
1,4141210
1,4141210
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f496213%2ffind-second-largest-value-in-array%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
What if
array=(1 2 7 6 7)
? What is the 2nd largest value, 6 or 7?– glenn jackman
Jan 23 at 15:38