①getRange().getValues()で取得した値で .some()は使えないのですか?
使えますが、質問の場合、下記のようにする必要があります(先に答えを示して、その後で解説します)
削除・修正したところはコメントアウトしています。
js
1function myFunction2() {
2 const ss = SpreadsheetApp.getActiveSpreadsheet();
3 const sheet = ss.getActiveSheet();
4
5 //const fruits = []; // 削除
6 //const myValue = sheet.getRange(4, 9, 4, 1).getValues();
7 const fruits = sheet.getRange(4, 9, 4, 1).getValues().flat(); // 修正
8
9 //fruits.push(myValue);
10 //console.log("fruits " + fruits);
11 console.log(fruits); // 修正
12 function checkAvailability(arr, val) {
13 return arr.some((arrVal) => val === arrVal);
14 }
15
16 const chk2 = checkAvailability(fruits, "banana");
17 console.log(chk2);
18}
ポイント1.getValues() で取得したデータの形を正しく確認する方法。
→ 配列の形を確認する場合は、GASではconsole.log の中で+記号等で文字列連結しない。
まず、OKバージョンとNGバージョンで出力結果が同じであるにもかかわらず、NGでは期待した結果が得られなかったのが、そもそもの疑問点であると理解しました。この点について説明します。
元の質問文では、
js
1console.log("fruits " + fruits);
というように、console.log の中で 'fruits' という文字列と、配列 fruits が連結されています。
しかし、console.log で 文字列と配列を+記号で連結してしまうと、配列の正しい形を確認することができません。
具体的に言うと、 fruitsは、
[[['apple'], ['banana'], ['mango'], ['guava']]]
のような形(配列の中に配列が入れ子になった3重の配列)になっていますが、
他の文字列と配列を+記号で連結して
js
1console.log("fruits" + fruits);
としてしまうと、表示上は入れ子が外れて、質問内の画像にあるように
fruits apple, banana, mango, guava
と表示されてしまいます。
(ただしこれはあくまで表示だけで、内部の配列の構造が変わっているわけではありません。またこのようになるのは、現時点のGASエディタ特有の現象であり、他の処理系では必ずしも同様になるとは限りません)
ここは、
のように、console.log関数の括弧の中に形を確認したい変数だけ入れることで、
[ [ ['apple'], ['banana'], ['mango'], ['guava'] ] ]
とそのままの形で出力されます。
または、出力したい文字列・項目をカンマで区切って指定することでも同じようにそのまま出力できます。
js
1const x = [['apple'], ['banana'], ['mango'], ['guava']];
2const y = [];
3y.push(x);
4console.log('x=', x, '\n', 'y=', y); //'\n'は改行
5
6出力結果
7>> x= [ ['apple'], ['banana'], ['mango'], ['guava'] ]
8>> y= [ [ ['apple'], ['banana'], ['mango'], ['guava'] ] ]
※誤解しないでいただきたいのですが、console.log の中で+記号で文字列連結をすること自体は特に間違いではありません。
ただ、現時点のGASエディタでは、console.log()を用いて配列の形を確認する際に+記号で連結すると、実際の配列の構造と異なる形で表示されてしまうという点に注意してほしい、ということです。
ポイント2.someで比較している対象
下記は、元のNGバージョンのコードで
console.log('fruits'+fruits);を
console.log(fruits);に直しただけのコードです。(途中まで)
js
1function myFunction2() {
2 const ss = SpreadsheetApp.getActiveSpreadsheet();
3 const sheet = ss.getActiveSheet();
4 const fruits = [];
5 const myValue = sheet.getRange(4, 9, 4, 1).getValues();
6
7 fruits.push(myValue);
8 console.log(fruits); // 修正
これを実行すると、
[[['apple'], ['banana'], ['mango'], ['guava']]]
と表示されます。
このfruits に対して、some を適用しても、期待通りの結果になりません。
なぜなら、
getgValues() で得た myValue の内容は [['apple'], ['banana'], ['mango'], ['guava']]となっていて
fruits はさらに []の中に myValueをpushしたものになっているからです(3重の入れ子)
js
1function myFunction2() {
2 const ss = SpreadsheetApp.getActiveSpreadsheet();
3 const sheet = ss.getActiveSheet();
4 const fruits = [];
5 const myValue = sheet.getRange(4,9,4,1).getValues();
6 fruits.push(myValue);
7 function checkAvailability(arr, val) {
8 return arr.some((arrVal) => val === arrVal);
9 }
10 const chk2 =checkAvailability(fruits, 'banana');
11 console.log(chk2);
12}
上はNGバージョンと同じコードですが、上のコードを実行した場合、 checkAvailability のarr には
myValue すなわち
[[['apple'], ['banana'], ['mango'], ['guava']]]
という3重の入れ子になった配列が渡され、
js
1 arr.some((arrVal) => val === arrVal);
の arrVal という引数には、
[[['apple'], ['banana'], ['mango'], ['guava']]]
の1つ内側の要素
[['apple'], ['banana'], ['mango'], ['guava']]
が渡されることになります。
結果
[['apple'], ['banana'], ['mango'], ['guava']]
と 'banana'
が等しいかどうかを1回だけ比較することになってしまい、これはfalse(等しくない)となります。
ポイント3.flat() 関数
ポイント2で、 getValues で得た myValue (fruitsにpushする前)は
[['apple'], ['banana'], ['mango'], ['guava']]
という形になっていますが、これを checkAvailability に渡しても
['apple'], ['banana'], ['mango'], ['guava'] というそれぞれの要素を 'banana'という文字と比較することになってしまい
すべて等しくない(false) となってしまいます。
本件で
arr.some((arrVal) => val === arrVal);
のところで期待するように some を動作させるには、
arr が1重の配列となっている必要があります。
「1重の配列」とは
[['apple'], ['banana'], ['mango'], ['guava']]
ではなく
['apple', 'banana', 'mango', 'guava']
の形です。
各要素から [ ] を取り外すには、flat() という関数を使います。
js
1const a = [['apple'], ['banana'], ['mango'], ['guava']];
2const b = a.flat();
3console.log(b);
4
5>>> ['apple', 'banana', 'mango', 'guava']
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
また依頼した内容が修正された場合は、修正依頼を取り消すようにしましょう。