【问题标题】:How to eliminate extra matches of element in single array如何消除单个数组中元素的额外匹配
【发布时间】:2015-06-07 19:53:15
【问题描述】:

我正在尝试返回数组的模式。我有一个内部循环和外部比较每个元素。数组 = [5,3,6,3,3,3]。

function mode(arr){
    for (var i = 0; i < arr.length; i++) {
        for (var k = i+1; k < arr.length; k++) {
            if (arr[i] == arr[k]) { 
            modeItems += arr[k];
            }else {
            otherItems +=arr[i];
        }
    }
}return modeItems;

}

结果返回“333333”而不是“3333”。我在比较 15 个总循环 aar[i] 和 arr[k] 的 Excel 工作表上看到这是如何发生的,但我不知道该怎么做。

【问题讨论】:

  • 看看modeItems,它是如何定义和返回的。
  • 我将它定义为一个空数组。我的目标是将匹配的元素从单个实例中分离出来
  • 您可以在O(nlogn) 时间内完成,而不是O(n^2)
  • 我是新程序员,你指的是大 O 符号?
  • 你在找这个吗? jsfiddle.net/7kp4ens9

标签: javascript arrays comparison


【解决方案1】:

下面是一个大杂烩的答案。我的困惑源于标题

如何消除单个数组中元素的额外匹配

混合这部分问题

我正在尝试返回数组的模式。


将数组简化为单个实例的数组,以及所有重复项的数组。

DEMO

var arra = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];

function simplify(arr) {
  var c = {}, o = [], d = [], i;
  
  for (i = 0; i < arr.length; i++) {
    if (!c.hasOwnProperty(arr[i])) {
      c[arr[i]] = arr[i];
      o.push(arr[i]);
    } else {
      d.push(arr[i]);
    }
  }
  
  return {
    reduced: o,
    duplicates: d
  };
}

console.log(simplify(arra));
// >> [object Object] {
// >>  duplicates: [2, 3, 3, 4, 4, 4],
// >>  reduced: [1, 2, 3, 4]
// >> }

就地从数组中删除重复项。

DEMO

var arr = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];

function elim (arra) {
  var c = {}, i = 0;
  
  while (i < arra.length) {
    if (c[arra[i]]) {
      arra.splice(i, 1);
    } else {
      c[arra[i]] = true;
      i++;
    }
  }
  
  return arra; // only required for debug.
}

console.log(elim(arr.slice()));

在一个数组上循环多次只是为了找到模式是不必要的。您可以使用对象文字作为缓存来更新计数。如果你想要一个减去模式的数组(或只有模式的数组),你可以在之后使用.filter

这是一个基本的实现。如果没有模式,我们返回 null。

DEMO

function findMode (a) {
  var cache = {},
      len = a.length,
      mode,
      max = 0,
      matched = false;
  
  for (var i = 0; i < len; i++) {
    cache[a[i]] = (cache[a[i]] + 1 || 1);
    
    if (cache[a[i]] === max) {
      matched = true;
    } else if (cache[a[i]] > max) {
      max = cache[a[i]];
      mode = a[i];
      
      matched = false;
    }
  }
  
  return (matched ? null : mode);
}

var arr = [5,3,6,3,3,3],
    myMode = findMode(arr),
    filteredArr = arr.filter(function (e) {
      return (e !== myMode);
    }),
    modeItems = arr.filter(function (e) {
      return (e === myMode);
    });

console.log(arr); // >> [5,3,6,3,3,3]
console.log(myMode); // >> 3
console.log(filteredArr); // >> [5, 6]
console.log(modeItems); // >> [3, 3, 3, 3]

这里没有模式:

findMode([5, 7, 5, 7]); // >> null

稍微复杂一些。在原始数组的两遍中返回模式、模式数组和逆数组。

DEMO

var findMode = (function () {
  function getMode (a) {
    var cache = {},
        len = a.length,
        mode,
        max = 0,
        matched = false;

    for (var i = 0; i < len; i++) {
      cache[a[i]] = (cache[a[i]] + 1 || 1);

      if (cache[a[i]] === max) {
        matched = true;
      } else if (cache[a[i]] > max) {
        max = cache[a[i]];
        mode = a[i];

        matched = false;
      }
    }

    return (matched ? null : mode);
  }
  
  function split (arr, mode) {
    var set = [],
        inverse = [];
    
    if (mode !== null) {
      for (var i = 0; i < arr.length; i++) {
        if (arr[i] === mode) {
          set.push(arr[i]);
        } else {
          inverse.push(arr[i]);
        }
      }
    }
    
    return [set, inverse];
  }
  
  
  return (function (arr) {
    var mode = getMode(arr),
        lists = split(arr, mode);
       
    return {
      mode: mode,
      set: lists[0],
      inverse: lists[1]
    };
  });
}());


var info = findMode([5,3,6,3,3,3]),
    noMode = findMode([5, 7, 5, 7]);

console.log(info);
console.log(noMode);

【讨论】:

  • 谢谢,好的。我正在尝试运行更复杂的示例并对其进行评论以了解其工作原理和原因。我对几个部分感到困惑。
  • This 可能会有所帮助。一些小的编辑和解释。请记住,这仅适用于所有字符串或所有数字的数组,因为对象属性是 always 字符串。 cache[55]cache['55'] 是同一个属性。您可以通过为每种类型设置缓存来解决此问题。这将从不对包含对象(或数组)的数组起作用,因为对象将被转换为相同的'[object Object]' 字符串,如果我们的模式是实际上,它将不起作用> null.
【解决方案2】:

维护一个对象数组来保存已处理的项目,并忽略下一个迭代器中已经处理的项目。

function mode(arr) {
var processed = {};
for (var i = 0; i < arr.length; i++) {
    for (var k = i + 1; k < arr.length; k++) {
        if (arr[i] == arr[k]) {
            modeItems += arr[k];
            modeItems += !processed[arr[k]] ? arr[k] : '';
            processed[arr[k]] = i;
            break;
        } else {
            otherItems += arr[i];
        }
      }
  }
  return modeItems;
}

Output: 3,3,3,3

【讨论】:

    【解决方案3】:

    您的代码正在匹配循环中的每个数字,索引i+1 之后的数字:

    [5,3,6,3,3,3]
       ^   ^       //first match
    [5,3,6,3,3,3]
       ^     ^    // match 2
    [5,3,6,3,3,3]
       ^       ^  // match 3
    [5,3,6,3,3,3]
           ^ ^    // match 4
    [5,3,6,3,3,3]
           ^   ^  // match 5
    [5,3,6,3,3,3]
             ^ ^  // match 6
    

    解决此问题的一种简单方法是如果 i 已经匹配,则使用 continue 重置循环;但如果你有多次重复出现,它会失败..

    【讨论】:

    • 我想说明那个测试用例
    【解决方案4】:

    让我也加上我的两分钱。此代码删除匹配的项目不再使用它:)

    function mode(arr){
       var key = arr[0],       // it wil be the mode, current value of array
            count = 1,          // it will be the count of mode value
            icount;
            for (var i = 0;  i < arr.length-count+1; i++) { // there is no need to look any further - 
                                                            // count is more then rest items
    
                if (!arr[i]) continue;
                icount = 1;
                for (var k = i+1; k < arr.length; k++) {
                    if (!arr[k]) continue;
                    if (arr[i] == arr[k]) {  icount++; delete arr[k]; }
                }
                if (icount > count) { count = icount; key = arr[i]; }
        }
        if (count == 1) ret = null;  // At this moment key - mode. Below output
        else {  var ret = []; while(count--) ret[count] = key; ret = ret.join();}
        return ret; 
     }
    

    【讨论】:

    • 我认为通过删除一个元素(在我最初发布的代码中),将通过相对于要搜索的内容“移动索引”位置来改变结果。
    • 不,我打印索引。不幸的是,他们没有改变。但是代码有效。为 arr.length-(count-1) 做更重要的事情。 Ii 确实减少了循环次数
    猜你喜欢
    • 2014-09-16
    • 1970-01-01
    • 1970-01-01
    • 2019-01-05
    • 1970-01-01
    • 2013-04-19
    • 2014-02-23
    • 1970-01-01
    • 2010-12-08
    相关资源
    最近更新 更多