From f9c4c1d12833699be11cb0bb13c6f1865ba00199 Mon Sep 17 00:00:00 2001 From: Steven Baltakatei Sandoval Date: Fri, 27 Oct 2023 11:51:04 +0000 Subject: [PATCH] feat(unitproc/bkt-get_median):Add Bash function to calculate median - Note: Accepts integers of floats from stdin. Does no input validation. --- unitproc/bkt-get_median | 78 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100755 unitproc/bkt-get_median diff --git a/unitproc/bkt-get_median b/unitproc/bkt-get_median new file mode 100755 index 0000000..bdf6a53 --- /dev/null +++ b/unitproc/bkt-get_median @@ -0,0 +1,78 @@ +#!/usr/bin/env bash + +read_stdin() { + # Desc: Consumes stdin; outputs as stdout lines + # Input: stdin (consumes) + # Output: stdout (newline delimited) + # Example: printf "foo\nbar\n" | read_stdin + # Depends: GNU bash (version 5.1.16) + # Version: 0.0.1 + local input_stdin output; + + # Store stdin + if [[ -p /dev/stdin ]]; then + input_stdin="$(cat -)"; + fi; + + # Store as output array elements + ## Read in stdin + if [[ -n $input_stdin ]]; then + while read -r line; do + output+=("$line"); + done < <(printf "%s\n" "$input_stdin"); + fi; + + # Print to stdout + printf "%s\n" "${output[@]}"; +}; # read stdin to stdout lines +get_median() { + # Desc: Gets the median from integers or floats read from stdin + # Input: stdin newline-delimited integers or floats + # Output: stdout float + # Depends: GNU Coreutils 8.32 (sort), bc 1.07.1 + # Depends: BK-2020-03: read_stdin() 0.0.1, + # Version: 0.0.1 + + # Read stdin + list="$(read_stdin)"; + + # Sort list + list="$(printf "%s\n" "$list" | sort -n)"; + + # Get list length + list_lc="$(printf "%s\n" "$list" | wc -l)"; + + # Get number of lines to trim from start and end + if [[ $((list_lc % 2)) -eq 0 ]]; then + # If even + trim=$(( list_lc / 2 - 1 )); + flag_even="true"; + else + # If odd + trim=$(( list_lc / 2 )); + fi; + + # Trim lines + list="$(printf "%s\n" "$list" | tail -n+$((trim+1)) | head -n-$((trim)) )"; + + # Get median + if [[ "$flag_even" == "true" ]]; then + ## Average remaining two lines + l1="$(printf "%s\n" "$list" | head -n1)"; + l2="$(printf "%s\n" "$list" | tail -n1)"; + median="$( echo "( $l1 + $l2 ) / 2" | bc -l; )"; + else + ## Median is simply remmaining line + median="$list"; + fi; + + # Output median + printf "%s" "$median"; + + # Author: Steven Baltakatei Sandoval + # License: GPLv3+ +}; # Returns median float from a list + +# Test +shuf -i1-100 -n49 | get_median; printf "\n"; +printf "17\n5\n11.1111\n3.141592\n2\n343.4343434343434343\n" | get_median; printf "\n"; -- 2.30.2