简体   繁体   中英

Delete array elements ksh

I need to delete specific values in an array (which vary in their index positions), similar to the splice function in javascript.

Example:

set -A ARRAY1 "a" "b" "c" "d" "e"
set -A ARRAY2 "a" "c" "e"

# Expected ARRAY1 after splice: "b" "d"

What I've tried:

I iterated through the arrays to find matches to the values I want deleted, and set them to empty ("").

ITERATION=0
for i in "${ARRAY1[@]}"
do
    for j in "${ARRAY2[@]}"
    do
        if [[ $i == $j ]]
        then
            ARRAY1[$ITERATION]=""
        fi
    done
    ITERATION=$((ITERATION+1))
done

#ARRAY1 after emptying values: "" "b" "" "d" ""

After that, I made a variable to store the concatenation of the first array's values.

VARIABLE=${ARRAY1[@]}

Then set the array back together again.

set -A ARRAY1 $VARIABLE
# VARIABLE: b d

Now the ARRAY1 has 2 indexes with values "b" and "d" as expected.

echo "ARRAY1: ${ARRAY1[@]}"
# output: ARRAY1: b d

I tried searching for the correct way to do this but couldn't find anything, and I think my solution is not right, even if it seems to work. Is there a correct or better way to do this? Is there a function for this in ksh?

Thanks in advance!

So, what you want to do is take the difference of sets. An indexed array is not a good representation of a set. However, the keys of an associative array is.

Try this:

array1=( "a" "b" "c" "d" "e" )
array2=( "a" "c" "e" )

# declare an associative array
typeset -A tmp                    

# populate it
for elem in "${array1[@]}"; do
  tmp[$elem]=1
done

# remove elements
for elem in "${array2[@]}"; do
  unset "tmp[$elem]"
done

# reassign the array with the keys of the assoc. array
array1=( "${!tmp[@]}" )

printf "%s\n" "${array1[@]}"
b
d

Get out of the habit of using ALLCAPS variable names, leave those as reserved by the shell. One day you'll write PATH=something and then wonder why your script is broken .

Using the same notation as the OP, just need one small change to the if/then block to unset the array position:

ITERATION=0
for i in "${ARRAY1[@]}"
do
    for j in "${ARRAY2[@]}"
    do
        if [[ $i == $j ]]
        then
            unset ARRAY1[$ITERATION]
        fi
    done
    ITERATION=$((ITERATION+1))
done

Here's a ksh fiddle of the above.

A quick dump of the current array:

echo "ARRAY1: ${ARRAY1[@]}"
ARRAY1: b d

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM