配列から、重複した配列を削除する方法はありますか。

MAXScript に関する質問と回答 > MAXScript 値の操作 > 配列から、重複した配列を削除する方法はありますか。

質問:

次のような複数の配列からなる配列があります。

#(#(1, 5), #(6, 10), #(6, 10), #(14, 18), #(14, 18))

どのようにすれば、重複した配列 (この場合、2 番目と 3 番目、4 番目と 5 番目) を検索して取り除くことができるでしょうか。

findItem を使用した場合、最初のインスタンスだけが返され、以降の検索が行われません。また、「for」ループをネストにして最初の数値と 2 番目の数値を比較しようとしましたが、考えている処理を行うようには設定できません。主に、配列をループで処理するときに、配列から項目を削除すると問題が起きてしまうようです。

回答:

デバッグ用の出力を追加したロング バージョンを示します。 これを見ればどのように処理されているかがわかります。

ループ処理を行っている配列から要素を削除するときに、必ず後方からカウントすることが重要になります。このようにしないと、要素が削除されたことより、配列項目の番号が更新されるため、ループが混乱してしまいます。

ロング バージョン:

(
theArray = #(#(1, 5), #(6, 10), #(6, 10), #(14, 18), #(14, 18))
print "Before:"
print theArray
fn compareSubArrays first second =
(
  result = true
  if first.count != second.count then
    result = false
  else
    for i = 1 to first.count do
  if first[i] != second[i] do result = false
  result
)
for i = 1 to theArray.count do
(
  for j = theArray.count to i+1 by -1 do
  (
    format "Comparing %:% to %:% \n" i theArray[i] j theArray[j]
    test = (compareSubArrays theArray[i] theArray[j])
    print test
    if test do
    (
      deleteItem theArray j
      format"Deleting %\n"j
    )
  )--end j loop
)--end i loop
print"After:"
print theArray
)

結果

"Before:"
#(1, 5)
#(6, 10)
#(6, 10)
#(14, 18)
#(14, 18)
Comparing 1:#(1, 5) to 5:#(14, 18)
false
Comparing 1:#(1, 5) to 4:#(14, 18)
false
Comparing 1:#(1, 5) to 3:#(6, 10)
false
Comparing 1:#(1, 5) to 2:#(6, 10)
false
Comparing 2:#(6, 10) to 5:#(14, 18)
false
Comparing 2:#(6, 10) to 4:#(14, 18)
false
Comparing 2:#(6, 10) to 3:#(6, 10)
true
Deleting 3
Comparing 3:#(14, 18) to 4:#(14, 18)
true
Deleting 4
"After:"
#(1, 5)
#(6, 10)
#(14, 18)
OK
OK

コメント付きのコンパクト バージョン:

(
theArray = #(#(1, 5), #(6, 10), #(6, 10), #(14, 18), #(14, 18))
--Function to compare the content of two arrays
fn compareSubArrays first second =
(
  result = true --init. return value to true
  if first.count != second.count then --if the count of the two subarrays is different,
    result = false--return false
  else --otherwise
    for i = 1 to first.count do --go through all elements in the arrays
  if first[i] != second[i] do result = false --and see if two elements are different
  result --return the result - true if identical, false if not
)
for i= 1 to theArray.count do --go through all elements of the main array
for j = theArray.count to i+1 by -1 do --go backwards from the last to the current+1
  if compareSubArrays theArray[i] theArray[j] do
    deleteItem theArray j --if identical, delete the one with the higher index
format "%\n" theArray --print the result to the Listener
)

結果:

#(#(1, 5), #(6, 10), #(14, 18))
OK
OK

関連事項