Reputation: 227
How can I sort the array order based on the list I predefined in Bash.
The list I predefined
fixed=(john doe mary ben)
The array I want it to change
changetimetotime=(ben-5 doe-1 john-1)
There are few criteria I need to meet
The bash code I need
The quantity of changetimetotime array not necessary have 3, sometimes is 1 value but the maximum is 4 value.
fixed array only provide name, changetimetotime provide version number too.
Once both criteria have been met, the array will change to below
changetimetotime=(john-1 doe-1 ben-5)
And I need to access the changetimetotime array outside of the loop.
Please help.
Upvotes: 0
Views: 47
Reputation: 19315
If elements are always included in predefined set using a sparse array
fixed=(john doe mary ben)
# to fill an associative array from fixed array
# if supported (bash >4) otherwise use a decoding function
declare -A hash=()
for i in "${!fixed[@]}"; do hash[${fixed[i]}]=$i; done
changetimetotime=(ben-5 doe-1 john-1)
newchangetimetotime=()
for element in "${changetimetotime[@]}"; do
index=${hash[${element%%-*}]}
newchangetimetotime[index]=$element
done
echo "${newchangetimetotime[@]}"
# overwrite array reindexing keys
changetimetotime=("${newchangetimetotime[@]}")
Otherwise, general case using a quicksort
# an associative array to decode names to an int
declare -A hash=([john]="1" [doe]="2" [mary]="3" [ben]="4")
# or to fill from fixed array
# declare -A hash=()
# for i in "${!fixed[@]}"; do hash[${fixed[i]}]=$i; done
# function used to compare two elements
# exit status is success (0) if first is less or equal to second
is_ordered () {
# if string after name can contain many '-', % may be changed to %% to remove logest matched suffix
# extract names from elements
local k1=${1%-*} k2=${2%-*}
local v1=${hash[$k1]} v2=${hash[$k2]}
(($v1<=$v2))
}
# recursive quick sort
qsort () {
local l=() g=() p=$1
r=()
shift || return
for i; do
if is_ordered "$i" "$p"; then
l+=("$i")
else
g+=("$i")
fi
done
qsort "${g[@]}"
g=("${r[@]}")
qsort "${l[@]}"
l=("${r[@]}")
r=("${l[@]}" "$p" "${g[@]}")
}
qsort "${changetimetotime[@]}"
changetimetotime=("${r[@]}")
Upvotes: 1