JavaScript, функция diff, возвращающая ту же строку - PullRequest
1 голос
/ 16 мая 2011

Мне было интересно, может ли кто-нибудь помочь мне с моей функцией сравнения. Предполагается найти разность между 2 входами. функция принимает 2 массива, так что если массив 1 имеет .. "word1", "word2", а массив 2 имеет "word1", "word2" и "word3", он должен просто вернуть "word3". это работает по большей части, но с определенным вводом ниже, это не работает.

function diff(a1, a2) {

if (a1.length > a2.length
       || a1.length == a2.length) {
    return [""];
}
a1 = a1.slice(0);
a2 = a2.slice(0);


for (i = 0; i < a1.length; i++) {
    for (k = 0; k < a2.length; k++) {
        if (a1[i] == a2[k]) {
            a1.splice(i, 1);
            a2.splice(k, 1);
        }
    }
}

for (j = 0; j < a2.length; j++) {
    for (p = 0; p < a1.length; p++) {
        if (a2[j] == a1[p]) {
            a2.splice(p, 1);
            a1.splice(j, 1);
        }
    }
}


a1 = a1.concat(a2);
return a1;
}

var s1 = ["one", "two", "three", "four",];
var s2 = ["one", "two", "three", "four", "five"];


document.write(diff(s1, s2));

ответ должен просто возвращать «пять», но возвращать «четыре», «четыре», «пять». помощь будет высоко ценится. я супер застрял. спасибо большое!

Ответы [ 4 ]

3 голосов
/ 16 мая 2011

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

function diff(a1, a2) {

  var aa1 = {}, aa2 = {}, res = [];

  // create an object from a1, containing value:array-index pairs:
  for (var i = 0; i < a1.length; i++) {
      aa1[a1[i]] = i;
  }
  // create an object from a2 like the one from a1
  for (var i = 0; i < a2.length; i++) {
      aa2[a2[i]] = i;
  }
  /**
    * loop through the first object (from a1)
    * if a value in this object is not found in 
    * the object from a2, push that value to 
    * the result array (res)
   */
  for (var l in aa1){
    if (aa1.hasOwnProperty(l) && !(l in aa2)) {
        res.push(a1[aa1[l]]);
    }
  }
  /**
    * but the second array can also contain
    * values differing from the values in the first.
    * So, repeat the above for the object created 
    * from a2
   */
  for (var l in aa2){
   if (aa2.hasOwnProperty(l) && !(l in aa1)) {
        res.push(a2[aa2[l]]);
   }
 }
 /**
   * now res contains all different values
   * note: double values are not counted
   * so ['one','two','tree'] vs ['one','two','four','four']
   * will return ['tree','four']
   * note2: if you want to find the first difference,
   * return res[0]
   */

 return res;
}

Если это только первое отличие, которое вы хотите найти, этот метод (только для массива) подойдет:

function diff(a1, a2) {
  var firstdiff = null, i = -1;

  /**
    * local function to check if value [val] 
    * exists in array [arr]. Called from
    * within the loops
    */
  function check(val,arr){
      var i = -1;
      while(++i<arr.length){
          if(val === arr[i]){ return true;}
      }
      return false;
  }
  // loop a1 and check values vs a2-values
  while (++i<a1.length){
    if (!check(a1[i],a2)) {
      return firstdiff = a1[i];
    }
  }
  // no difference found, continue a2 vs a1
  i = -1;
  while (++i<a2.length){
    if (!check(a2[i],a1)) {
      return firstdiff = a2[i];;
    }
  }
  // there are no differences, firstdiff = null
  return firstdiff;
}
2 голосов
/ 16 мая 2011

Проблема в том, что array.splice уменьшает длину массива, таким образом заставляя цикл for пропускать элементы.Возможное решение - уменьшить значение итератора.

EDIT:

Когда вы объединяете массив, он удаляет элементы из массива, делая его короче.Итак, давайте предположим, что мы выполняем этот код:

test_array = [1, 2, 3, 4, 5];
for(i = 0; i < test_array.length; i++) {
    document.write(test_array[i]);
    if(i == 2) {
        test_array.splice(i, 1);
    }
}

вы можете видеть, что он выводит 1235, а не 12345. Это может произойти потому, что когда i = 2 и элемент удален, все элементы в массивепересчитать их индексТаким образом, если перед сращиванием массив будет:

  • [0] = 1
  • [1] = 2
  • [2] = 3
  • [3] = 4
  • [4] = 5

после того, как оно становится:

  • [0] = 1
  • [1] = 2
  • [2] = 4
  • [3] = 5

Между тем цикл for переходит к i = 3, но вместо test_array[3] 4, теперь 5, поэтому число 4 было пропущено.

Простое решение для этого - уменьшить число итераторов.

Пример:

test_array = [1, 2, 3, 4, 5];
for(i = 0; i < test_array.length; i++) {
    document.write(test_array[i]);
    if(i == 2) {
        test_array.splice(i, 1);
        i--;
    }
}
1 голос
/ 17 мая 2011

Этот комментарий быстро объясняет, что делал ваш код:

@Crystal, first double loop: at i=0 k=0 "one"=="one" so each is removed; at i=0 k=1 "two"!="three"; at i=0 k=2 "two"!="four"; at 0 3 "two"!="five"; 1 0 "three"!="two"; 1 1 "three"=="three" so each is removed; 1 2 "four"!="five"; no more cycles. In the second double loop: 0 0 "two"=="two" so each is removed; 0 1 is not run because at this point a1 only has "four" so a1.length==1. Thus we concat "four" in a1 with "four" and "five" in a2

Чтобы получить нужный ответ, измените

a1.splice(i, 1);

на

a1.splice(i--, 1);

Ипромойте, повторите для других 3 аналогичных случаев в двойных петлях.Таким образом, у вас будет 4 случая использования соединения и уменьшения на один его первый аргумент.Это уменьшение компенсирует удаление соединения.

Однако теперь вам нужен только один из двойных циклов, поскольку он удалит все перекрытия.

Кроме того, почему у вас есть проверка сверхуотфильтровать случаи, когда длина a1 больше или равна длине a2?Удалите и этот раздел.

Ответ будет "пять".При желании вы можете протестировать очень разные данные, и они должны работать.

Так что это может быть ваша программа:

function diff(a1, a2) {

a1 = a1.slice(0);
a2 = a2.slice(0);


for (i = 0; i < a1.length; i++) {
    for (k = 0; k < a2.length; k++) {
        if (a1[i] == a2[k]) {
            a1.splice(i--, 1);
            a2.splice(k--, 1);
        }
    }
}


a1 = a1.concat(a2);
return a1;
}

var s1 = ["one", "two", "seven", "three", "four",];
var s2 = ["one", "two", "four", "five", "six"];


document.write(diff(s1, s2));
0 голосов
/ 16 мая 2011

Вы перебираете массив во время его объединения, но вы не подстраиваетесь под это с помощью своих индексов.

...