配列に別の配列が含まれているかどうかを確認する必要があります。サブアレイの順序は重要ですが、実際のオフセットは重要ではありません。これは次のようになります。
var master = [12, 44, 22, 66, 222, 777, 22, 22, 22, 6, 77, 3];
var sub = [777, 22, 22];
したがって、master
にsub
が含まれているかどうかを知りたいのです。
if(master.arrayContains(sub) > -1){
//Do awesome stuff
}
では、これをエレガントで効率的な方法でどのように行うことができますか?
fromIndex
パラメータから少し助けを借りて
このソリューションは、配列の場合に要素を検索するための位置を開始するためのインデックスのクロージャを特徴としています。サブ配列の要素が見つかった場合、次の要素の検索は増分インデックスから始まります。
function hasSubArray(master, sub) {
return sub.every((i => v => i = master.indexOf(v, i) + 1)(0));
}
var array = [12, 44, 22, 66, 222, 777, 22, 22, 22, 6, 77, 3];
console.log(hasSubArray(array, [777, 22, 22]));
console.log(hasSubArray(array, [777, 22, 3]));
console.log(hasSubArray(array, [777, 777, 777]));
console.log(hasSubArray(array, [42]));
ちょっと考えただけですが、効率はアレイのサイズに依存します
var master = [12, 44, 22, 66, 222, 777, 22, 22, 22, 6, 77, 3];
var sub = [777, 22, 22];
if ((master.toString()).indexOf(sub.toString()) > -1 ){
//body here
}
[〜#〜]編集[〜#〜]
最初は誤解された質問。
_function arrayContainsSub(arr, sub) {
var first = sub[0],
i = 0,
starts = [];
while (arr.indexOf(first, i) >= 0) {
starts.Push(arr.indexOf(first, i));
i = arr.indexOf(first, i) + 1;
}
return !!starts
.map(function(start) {
for (var i = start, j = 0; j < sub.length; i++, j++) {
if (arr[i] !== sub[j]) {
return false;
}
if (j === sub.length - 1 && arr[i] === sub[j]) {
return true;
}
};
}).filter(function(res) {
return res;
}).length;
}
_
このソリューションは、使用可能なすべての開始点を再帰的にチェックするため、サブの最初のインデックスが配列内で一致する点
古い回答誰かが検索するのに役立つ場合に備えて保管しました。
if(master.indexOf(sub) > -1){ //Do awesome stuff }
これはmaster
が文字通りsub
を参照する場合にのみ一致することを覚えておくことが重要です。同じ内容の配列が含まれているだけで、異なる特定のオブジェクトを参照している場合、一致しません。
順序が重要な場合は、実際にはサブ配列(配列のサブセットではない)である必要があり、値が厳密に整数である場合は、これを試してください。
console.log ( master.join(",").indexOf( subarray.join( "," ) ) == -1 )
値のみをチェックする場合は、これをチェックしてください fiddle (サードパーティのライブラリを使用しません)
var master = [12, 44, 22, 66, 222, 777, 22, 22, 22, 6, 77, 3];
var sub = [777, 22, 22];
function isSubset( arr1, arr2 )
{
for (var i=0; i<arr2.length; i++)
{
if ( arr1.indexOf( arr2[i] ) == -1 )
{
return false;
}
}
return true;
}
console.log( isSubset( master, sub ) );
説明されているより速いオプションがあります ここ も。
このようにfilterとindexOfで試すことができます:
注:このコードは、サブ配列の順序をカバーしていない場合に機能します。
Array.prototype.arrayContains = function (sub) {
var self = this;
var result = sub.filter(function(item) {
return self.indexOf(item) > -1;
});
return sub.length === result.length;
}
例 ここ 。
UPDATED:マスター内のサブ配列のインデックスを返します(サブ配列のカバー順序)
Array.prototype.arrayContains = function(sub) {
var first;
var prev;
for (var i = 0; i < sub.length; i++) {
var current = this.indexOf(sub[i]);
if (current > -1) {
if (i === 0) {
first = prev = current;
continue;
} else {
if (++prev === current) {
continue;
} else {
return -1;
}
}
} else {
return -1;
}
}
return first;
}
デモ: ここ
同様の問題があり、セットを使用して解決しました。
function _hasSubArray( mainArray, subArray )
{
mainArray = new Set( mainArray );
subArray = new Set( subArray );
for ( var element of subArray )
{
if ( !mainArray.has( element ) )
{
return false;
}
}
return true;
}
この答えのために、私はサブ配列の順序を保持しています。つまり、サブ配列の要素は連続した順序である必要があります。マスターとの比較中に余分な要素がある場合、それはfalseになります。
私は3つのステップでそれをやっています:
sub
内のmaster
の最初の要素のインデックスを見つけて、配列matched_index[]
に格納します。matched_index[]
の各エントリについて、sub
の各要素がs_index
から始まるmaster
と同じであるかどうかを確認します。一致しない場合は、false
を返し、subのforループを中断し、matched_index[]
の次の要素の次のforループを開始します。sub
配列がmaster
で見つかった場合、ループは中断され、trueを返します。function hasSubArray(master,sub){
//collect all master indexes matching first element of sub-array
let matched_index = []
let start_index = master.indexOf(master.find(e=>e==sub[0]))
while(master.indexOf(sub[0], start_index)>0){
matched_index.Push(start_index)
let index = master.indexOf(sub[0], start_index)
start_index = index+1
}
let has_array //flag
for(let [i,s_index] of matched_index.entries()){
for(let [j,element] of sub.entries()){
if(element != master[j+s_index]) {
has_array = false
break
}else has_array = true
}
if (has_array) break
}
return has_array
}
var master = [12, 44, 22, 66, 222, 777, 22, 22, 22, 6, 77, 3];
console.log(hasSubArray(master, [777, 22, 22]));
console.log(hasSubArray(master, [777, 22, 3]));
console.log(hasSubArray(master, [777, 777, 777]));
console.log(hasSubArray(master, [44]));
console.log(hasSubArray(master, [22, 66]));
以下のこのスニペットを実行すると、機能するはずです
x = [34, 2, 4];
y = [2, 4];
y.reduce((included, num) => included && x.includes(num), true);
編集:@AlexanderGromnitskyあなたは正しいですこのコードは正しくありません、そしてキャッチしてくれてありがとう!上記のコードは、実際にはopが要求したことを実行しません。私は質問を十分に詳しく読んでおらず、このコードは順序を無視しています。 1年後、ここに私が思いついたものがあり、うまくいけば、これが誰かを助けるかもしれません。
var master = [12, 44, 22, 66, 222, 777, 22, 22, 22, 6, 77, 3];
var sub = [777, 22, 22];
var is_ordered_subset = master.join('|').includes(sub.join('|'))
このコードはややエレガントで、opが要求することを実行します。セパレータは、intでない限り重要ではありません。