javascript Javascript数组包含/包含子数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34151834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 17:19:15  来源:igfitidea点击:

Javascript array contains/includes sub array

javascriptarraysincludecontainsindexof

提问by Victor Axelsson

I need to check if an array contains another array. The order of the subarray is important but the actual offset it not important. It looks something like this:

我需要检查一个数组是否包含另一个数组。子数组的顺序很重要,但实际偏移量并不重要。它看起来像这样:

var master = [12, 44, 22, 66, 222, 777, 22, 22, 22, 6, 77, 3]; 

var sub = [777, 22, 22]; 

So I want to know if mastercontains subsomething like:

所以我想知道是否master包含以下内容sub

if(master.arrayContains(sub) > -1){
    //Do awesome stuff
}

So how can this be done in an elegant/efficient way?

那么如何以一种优雅/高效的方式做到这一点呢?

回答by Nina Scholz

With a little help from fromIndexparameter

fromIndex参数的帮助下

This solution features a closure over the index for starting the position for searching the element if the array. If the element of the sub array is found, the search for the next element starts with an incremented index.

该解决方案的特点是在索引上有一个闭包,用于开始搜索元素的位置,如果是数组。如果找到子数组的元素,则从递增索引开始搜索下一个元素。

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]));

回答by Mahesh Talada

Just came up with quick thought , but efficiency depends on size of the array

只是想出了一个快速的想法,但效率取决于数组的大小

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
}

回答by Mild Fuzz

EDIT

编辑

Misunderstood question initially.

最初误解了问题。

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;
    }

This solution will recursively check all available start points, so points where the first index of the sub has a match in the array

此解决方案将递归检查所有可用的起点,因此点在数组中子的第一个索引匹配的地方



Old AnswerKept in case useful for someone searching.

旧答案保留以防万一对某人搜索有用。

if(master.indexOf(sub) > -1){ //Do awesome stuff }

if(master.indexOf(sub) > -1){ //Do awesome stuff }

Important to remember that this will only match of masterliterally references sub. If it just contains an array with the same contents, but references a different specific object, it will not match.

重要的是要记住,这只会匹配master字面引用sub。如果它只是包含一个内容相同的数组,但引用了不同的特定对象,则它不会匹配。

回答by gurvinder372

If the order is important, it has to be an actually sub-array (and not the subset of array) and if the values are strictly integers then try this

如果顺序很重要,它必须是一个实际的子数组(而不是数组的子集),如果值是严格的整数,那么试试这个

console.log ( master.join(",").indexOf( subarray.join( "," ) ) == -1 )

for checking only values check this fiddle(uses no third party libraries)

只检查值检查这个小提琴(不使用第三方库)

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 ) );

There are faster options explained hereas well.

这里也解释更快的选项。

回答by Nguyen Tran

You can try with filterand indexOflike this:

您可以尝试使用filterindexOf ,如下所示:

Note: This code works in case we do not cover the order in sub array.

注意:此代码适用于我们不涵盖子数组中的顺序的情况。

Array.prototype.arrayContains = function (sub) {
  var self = this;
  var result = sub.filter(function(item) {
    return self.indexOf(item) > -1;
  });
  return sub.length === result.length;
}

Example here.

示例在这里

UPDATED:Return index of sub array inside master (cover order in sub array)

更新:返回主内子数组的索引(子数组中的覆盖顺序)

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;
}

Demo: here

演示:这里

回答by Matt Dabit

If run this snippet below it should work

如果在下面运行此代码段,它应该可以工作

x = [34, 2, 4];
y = [2, 4];
y.reduce((included, num) => included && x.includes(num), true);

EDIT: @AlexanderGromnitsky You are right this code is incorrect and thank you for the catch! The above code doesn't actually do what the op asked for. I didn't read the question close enough and this code ignores order. One year later here is what I came up with and hopefully this may help someone.

编辑:@AlexanderGromnitsky 你说得对,这段代码不正确,谢谢你的发现!上面的代码实际上并没有按照操作的要求执行。我没有足够仔细地阅读问题,这段代码忽略了顺序。一年后,这是我想出的,希望这可以帮助某人。

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('|'))

This code is somewhat elegant and does what op asks for. The separator doesn't matter as long as its not an int.

这段代码有点优雅,可以满足 op 的要求。分隔符无关紧要,只要它不是 int 即可。

回答by ProgrammingChobo89

I had a similar problem and resolved it using sets.

我有一个类似的问题并使用集合解决了它。

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;
}

回答by Jaimin Patel

For this answer, I am preserving the order of sub-array. Means, the elements of sub-array should be in Consecutive order. If there is any extra element while comparing with the master, it will be false.

对于这个答案,我保留子数组的顺序。意味着,子数组的元素应该是连续的。如果与master比较时有多余的元素,则为false。

I am doing it in 3 steps:

我分三步做:

  1. Find the index of the first element of subin the masterand store it an array matched_index[].
  2. for each entry in matched_index[]check if each element of subis same as masterstarting from the s_index. If it doesn't match then return falseand break the for loop of sub and start next for-loop for next element in matched_index[]
  3. At any point, if the same subarray is found in master, the loop will break and return true.
  1. 发现的第一个元素的索引sub中的master,并存储它的阵列matched_index[]
  2. 对于matched_index[]检查每个条目的每个元素sub是否与masters_index. 如果不匹配,则返回false并中断 sub 的 for 循环并开始下一个 for 循环中的下一个元素matched_index[]
  3. 在任何时候,如果在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]));

回答by Shravan

Try using everyand indexOf

尝试使用everyindexOf

var mainArr = [1, 2, 3, 4, 5]
var subArr = [1, 2, 3]

function isSubArray(main, sub) {
    return sub.every((eachEle) => {
        return (main.indexOf(eachEle) + 1);
    });
}
isSubArray(mainArr, subArr);