在数组中获取计数为偶数或计数大于2的元素

时间:2019-02-22 12:41:09

标签: javascript arrays

我正在尝试获取数组中计数为偶数的元素,我具有以下代码。 说我检查这个数组:

function checkEither(arr) {
  var newArr = [];
  for (var i = 0; i < arr.length; i++) {
      var count = 0;
      for (var j = 0; j < arr.length; j++) {
          if (arr[j] == arr[i]) {
              count++;
          }
      }
      if ((count >= 3) || (count % 2 == 0)) {
          newArr.push(arr[i]);
      }
  }
  return newArr;
}


console.log(checkEither([10, 11, 12, 11, 10, 10, 13, 11, 12, 10, 13, 14, 11, 10, 12]));

我明白了

[ 10, 11, 12, 11, 10, 10, 13, 11, 12, 10, 13, 11, 10, 12 ]

代替

[ 10, 11, 12, 11, 10, 10, 13, 11, 12, 10, 13, 11 ]

该数组仍应包含出现奇数项的项目,但结果应显示该项目的偶数

10出现五次,并且在新数组中应该只有四次。我该怎么办?谢谢

4 个答案:

答案 0 :(得分:2)

这是问题所在:

if ((count >= 3) || (count % 2 == 0)) {

也就是说,如果条目的计数大于或等于3 个计数为偶数,则包括该条目。因此,如果计数为5,则它匹配第一个条件并包含在内。

如果只想计数,请删除第一个条件:

if (count % 2 == 0) {

因为其中有5次出现,所以不会出现10个结果。

实时示例:

function checkEither(arr) {
  var newArr = [];
  for (var i = 0; i < arr.length; i++) {
    var count = 0;
    for (var j = 0; j < arr.length; j++) {
      if (arr[j] == arr[i]) {
        count++;
      }
    }
    if (count % 2 == 0) {
      newArr.push(arr[i]);
    }
  }
  return newArr;
}

console.log(checkEither([10, 11, 12, 11, 10, 10, 13, 11, 12, 10, 13, 14, 11, 10, 12]));

如果您还希望结果仅一次而不是重复包含每个数字,则需要检查结果数组中是否已经包含该数字,请参见***行:

function checkEither(arr) {
  var newArr = [];
  for (var i = 0; i < arr.length; i++) {
    if (!newArr.includes(arr[i])) { // ***
      var count = 0;
      for (var j = 0; j < arr.length; j++) {
        if (arr[j] == arr[i]) {
          count++;
        }
      }
      if (count % 2 == 0) {
        newArr.push(arr[i]);
      }
    }
  }
  return newArr;
}

console.log(checkEither([10, 11, 12, 11, 10, 10, 13, 11, 12, 10, 13, 14, 11, 10, 12]));

这涉及到每次重新扫描newArr,这对于小型阵列(例如所讨论的阵列,甚至中等大小的阵列)来说绝对合适。对于非常大的数组,您可能希望跟踪Set(或对象(如果必须支持过时的平台,则为对象)中的已知数字),因为使用Set的查找时间比线性查找时间要好:

function checkEither(arr) {
  var checked = new Set();          // ***
  var newArr = [];
  for (var i = 0; i < arr.length; i++) {
    if (!checked.has(arr[i])) {     // ***
      var count = 0;
      for (var j = 0; j < arr.length; j++) {
        if (arr[j] == arr[i]) {
          count++;
        }
      }
      if (count % 2 == 0) {
        newArr.push(arr[i]);
        checked.add(arr[i]);        // ***
      }
    }
  }
  return newArr;
}

console.log(checkEither([10, 11, 12, 11, 10, 10, 13, 11, 12, 10, 13, 14, 11, 10, 12]));

答案 1 :(得分:1)

您可以使用Array.prototype.filter两次来完成所需的操作。

在内部filter函数(checkItem)中,您需要找到一个项目在数组中存在的次数,并获取最后一个索引。

外部filter函数(checkEither)中的int如果计数可以被2整除并且该项目不是其类型的最后一个项目,则返回true。

function checkEither(arr) {
  return arr.filter(function(item, index) {
    var { lastIndex, result } = checkItem(arr, item);
    return (result % 2 === 0) || (lastIndex !== index);
  });
}

function checkItem(arr, item) {
  var lastIndex = 0;
  var result = arr.filter(function(val, index) {
    var areEqual = val === item;
    if (areEqual) lastIndex = index;
    return areEqual;
  }).length;
  return { lastIndex, result };
}

console.log(checkEither([10, 11, 12, 11, 10, 10, 13, 11, 12, 10, 13, 14, 11, 10, 12]));
console.log(checkEither([1, 1, 2, 3, 3, 3]));

为提高效率,您可以缓存每个项目的结果,以避免多次检查同一项目。

function checkEither(arr) {
  var results = {};
  return arr.filter(function(item, index) {
     results[item] = results[item] || checkItem(arr, item);
     var { lastIndex, result } = results[item];
    return (result % 2 === 0) || (lastIndex !== index);
  });
}

function checkItem(arr, item) {
  var lastIndex = 0;
  var result = arr.filter(function(val, index) {
    var areEqual = val === item;
    if (areEqual) lastIndex = index;
    return areEqual;
  }).length;
  return { lastIndex, result };
}

console.log(checkEither([10, 11, 12, 11, 10, 10, 13, 11, 12, 10, 13, 14, 11, 10, 12]));
console.log(checkEither([1, 1, 2, 3, 3, 3]));

答案 2 :(得分:0)

您可以获取计数,将值调整为偶数,然后通过减少计数进行过滤。

module.exports = function (env) {

env = env || {};
var isProd = env.NODE_ENV === 'production';

// Setup base config for all environments
var config = {
    context: path.resolve(__dirname, "Features"),
    entry: {
        "Maps": [ "./Map/Scripts/map.js"],
    },
    output: {
        path: path.join(__dirname, 'wwwroot/dist'),
        filename: '[name].js'
    },
    devtool: 'source-map',
    resolve: {
        extensions: ['.ts', '.tsx', '.js', '.jsx']
    },
    module: {
        rules: [
            { test: /\.css?$/, use: ['style-loader', 'css-loader'] },
            { test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' },
            { test: /\.(png|woff|woff2|eot|ttf|svg)(\?|$)/, use: 'url-loader?limit=100000' },
            { test: /\.tsx?$/, use: "ts-loader", exclude: /node_modules/ }
        ]
    }
}
return config;

使用对象和触发器将值从function checkEither(array) { var count = array.reduce((c, v) => (c[v] = (c[v] || 0) + 1, c), {}); Object.keys(count).forEach(k => count[k] = count[k] >> 1 << 1); return array.filter(v => count[v] && count[v]--); } console.log(checkEither([10, 11, 12, 11, 10, 10, 13, 11, 12, 10, 13, 14, 11, 10, 12]).join(' '));更改为实际索引(对于不均匀计数),反之亦然,对于偶数计数,只有两个循环的解决方案。

  

例如使用undefined

10

结果是过滤后的不包含元素的数组,这些元素具有存储的值索引。

index  indices[10]  comment
-----  -----------  ------------------------------------
        undefined   at start
    0          0   
    4   undefined
    5          5 
    9   undefined
   13         13   at this index, the value is filtered

答案 3 :(得分:0)

仅需注意,此解决方案具有O(n ^ 2),对于更大的数据集将是可怕的。取决于输入集(如果所有输入都是体面范围内的整数),则可以在数字和辅助数组索引之间进行投影,其中index表示第一个数组中数字的值。然后,在该索引上,每当在第一个数组中找到该值时,就增加1。最后,您从头到尾读取了该数组(辅助对象1),并在其中列出了每个偶数的索引。

在该解决方案中,您拥有O(2n),即O(n),自己计算一组仅10k大数组的时间差;)

您可以在这里找到带有图片的方法,而不是更详细;)

indexing array values in another array

请注意,您也可以使用十进制数字数组(乘以10 ^ n并得到所有整数),负数(从最左边的1移到0并在此处开始索引)进行此操作。

对我来说,任何非初级程序员都不会接受将线性时间(和一个简单的实现)上的二次时间复杂度作为可行的解决方案,除非已知数据集很小且永远不会增长。