2016-10-11 10 views
2

Я пытаюсь пропустить массив массивов и сравнить элементы друг с другом, чтобы найти общие элементы. так что скажем, если у нас есть var arr = [[1,2,3],[4,2,5]]; Я хочу сначала сравнить [i] [i] и [i + 1] [i], [i] [i + 1] и [i + 1] [i + 1] и [i ] [i + 2] и [i + 1] [i + 2] и т. д. Вот мой код:сравнить элементы массива из множества массивов

function sym(args) { 
    var fullArr = []; 
    var finalArr = []; 
    // store the arguments inside a single array 
    for (var count = 0; count < arguments.length; count ++) { 
    fullArr[count] = arguments[count]; 
    } 
    // loop through finalArr[]; 
    for (var i = 0; i < fullArr.length; i++) { 
    if (fullArr[i][i] == fullArr[i++][i++]) { 
     // if the element matches (it is a common element) 
     // store it inside finalArr 
     finalArr[i] = fullArr[i]; 
    } 
    } 
    return finalArr; 
} 

sym([1, 2, 3], [5, 2, 1, 4]); 

проблема: когда я запускаю код вместо массива, содержащего соответствующий элемент, я получаю пустой массив

+0

'fullArr [i ++] [i ++]' не делает то, что вы думаете. Это увеличивает время i * каждый раз, и это невероятно плохая практика (даже когда она работает), потому что люди, читающие ее, не могут помнить, что я сначала увеличиваю, поэтому они не уверены, означает ли это 'fullArr [1] [2] 'или' fullArr [2] [1] ' –

+0

. Что, если список 1 был 1,1,2,3, а список 2 - 1,1,1,2,3? Сколько раз должно появляться 1 в конечном выходном массиве –

+0

Также вы указали, что делать, если есть n массивов .... мы просто собираем только те значения, которые являются общими для всех трех? –

ответ

1

Вы должны сначала перебрать один массив и посмотреть, если другие массив содержит указанное вами значение.

Мой ответ аналогичен вложенному циклу в том, что метод includes делает именно это. Он принимает в качестве параметра элемент и проверяет, содержит ли указанный в нем массив указанный элемент. Для этого он должен перебирать все элементы массива в худшем случае.

В ответе также предполагается, что вы хотите только один раз подсчитать повторяющиеся совпадения.

function sym(args) { 
 
    var fullArr = []; 
 
    var finalArr = []; 
 
    // store the arguments inside a single array 
 
    for (var count = 0; count < arguments.length; count ++) { 
 
    fullArr[count] = arguments[count]; 
 
    } 
 
    // loop through finalArr[]; 
 
    
 
    //since you are comparing only two arrays in this 
 
//example you just have to iterate over each element in the first array aka fullArr[0] and 
 
//check if each element "e" is also in the second array aka fullArr[1] 
 
//AND that your final output array does not already contain it. 
 
//If both of these are true then we push the element to the output array. 
 
    fullArr[0].forEach(function(e){ 
 
     if(fullArr[1].includes(e) && !finalArr.includes(e)) finalArr.push(e); 
 
    
 
    }); 
 
    return finalArr; 
 
} 
 

 
sym([1, 2, 3], [5, 2, 1, 4]);

Однако, если вы хотите, чтобы проверить, является ли конкретный элемент существует в всех коллекций массива длины п, то я хотел бы предложить что-то вроде этого:

function sym(args) { 
 
    var fullArr = []; 
 
    var finalArr = []; 
 
    // store the arguments inside a single array 
 
    for (var count = 0; count < arguments.length; count ++) { 
 
    fullArr[count] = arguments[count]; 
 
    } 
 
     
 
     var newArr = fullArr[0].reduce(function(prev, e1) { 
 
     if(prev.indexOf(e1) < 0 && fullArr.every(function(arr){ 
 
        return arr.indexOf(e1) > -1; 
 
      })){ 
 
      return [...prev, e1];  
 
      }else{ 
 
        return prev; 
 
      }; 
 
     },[]); 
 
     alert(newArr);   
 
     return newArr; 
 
} 
 

 
sym([1,1, 2, 3,4], [5, 2, 1, 4], [4,1,2, 5]);

+0

спасибо за ответ, когда я запускаю ваш первый код, я получаю эту ошибку: TypeError: fullArr [1] .includes - это не функция – zamzam

+0

попробуйте мое второе решение с indexof –

+0

Также я до сих пор не знаю, хотите ли вы пересечения через n массивов ... как вы настраиваете свою функцию, кажется, что вы это делаете. –

0

В вашей код, когда выполняется следующая строка, вы также увеличить значение i которое является вашей управляющей переменной:

if (fullArr[i][i] == fullArr[i++][i++])

Таким образом, это то, как ваша i переменная получает приращение в каждой итерации:

Iteration # 1:i = 0

Итерация # 2:i = 3 - вы получите я + 2 из строка, о которой я упоминал выше, +1 больше от инкремента, который вы указываете в конечном состоянии цикла for

Таким образом, даже после первой итерации ваша функция вернет пустой массив в вашем конкретном сценарии, так как вы передавая массив длиной 3, а цикл for заканчивается после i = 0 на первой итерации.

Даже если цикл будет продолжаться, он вернет исключение индекса за пределы, потому что ваш массив длины 3 не будет иметь элемент array[3].

Например, если вы хотите сравнить только два массива, как в вашем случае, вам нужно перебрать каждый из них и сравнить их элементы:

function sym(array1, array2) { 
    var results = []; 


    for (var i = 0; i < array1.length; i++) { 
     for (var j = 0; j < array2.length; j++) { 
      if(array1[i] === array2[j]) { 
       if(results.indexOf(array1[i]) === -1) { 
        results.push(array1[i]); 
       } 
      } 
     } 
    } 

    return results; 
} 

sym([1, 2, 3], [5, 2, 1, 4]); 

Я также построил решение, возвращающую пересечение массивов, которые вы предоставляете в качестве параметров для функции, независимо от того, сколько массивов есть:

function sym(args) { 
    var paramSet = Array.prototype.slice.call(arguments); 
    var counterObject = {}; 
    var results = []; 

    paramSet.forEach(function (array) { 
     // Filter the arrays in order to remove duplicate values 
     var uniqueArray = array.filter(function (elem, index, arr) { 
      return index == arr.indexOf(elem); 
     }); 


     uniqueArray.forEach(function (element) { 
      if (Object.prototype.hasOwnProperty.call(counterObject, element)) { 
       counterObject[element]++; 
      } else { 
       counterObject[element] = 1; 
      } 
     }); 
    }); 


    for (var key in counterObject) { 
     if (counterObject[key] === paramSet.length) { 
      results.push(parseInt(key)); 
     } 
    } 

    return results; 

} 

sym([1, 2, 3, 3, 3], [5, 2, 1, 4], [1, 7, 9, 10]); 

Приведенные выше код будет возвращать [1] для примера, который я представил, как это пересечение всех- массивы.

+0

Это приведет к дублированным совпадениям (предполагается, что мы не хотим, чтобы они были), если во втором списке элемент появляется более одного раза и соответствует только одному элементу в первом списке. –

+0

Действительно - спасибо, что указали это. Теперь я исправил свой код для учета возможных дубликатов. –

+0

close .... но теперь проблема в том, что если 1 появляется более одного раза в любом из массивов, он исчезнет из набора результатов. Кроме того, если 1 появился дважды во втором массиве, например, и 0 раз в третьем массиве, то ваша реализация все равно будет иметь его в наборе результатов. –

1

Вы можете выполнить итерацию по первому массиву и проверить, являются ли какие-либо его значения общепринятыми для всех других массивов.

function sym() { 
    var common = []; 
    for (var i=0; i<arguments[0].length; i++) { 
     var isCommon = common.indexOf(arguments[0][i]) === -1; // first check if its not already exists in the common array 
     for (var j=1; j<arguments.length && isCommon; j++) { 
      isCommon = arguments[j].indexOf(arguments[0][i]) > -1 
     } 
     if (isCommon) common.push(arguments[0][i]) 
    } 
    return common; 
} 

Конечно, вы можете улучшить его, итерации по самому маленькому массиву.

+0

Это хорошее решение –

+0

@naortor не могли бы вы объяснить, что происходит в этой строке: for (var j = 1; j zamzam

+0

@zamzam - в этом цикле я зацикливаюсь через все остальные массивы и проверить, есть ли значение аргументов [0] [i] во всех них - если я нашел один массив, значение аргумента [0] [i] не находится в нем - нет смысла в непрерывном цикле , lt; dr цикл через весь другой массив, а isCommon - true. – naortor