从数组中检索均匀分布的元素数

时间:2015-09-07 13:01:23

标签: javascript arrays

我知道如何提取数组中的每个第n项,但我遇到的困难如下:

如何从1800个元素的数组中提取每个第n个项目,总是包括第一个和最后一个元素,最多总共256个元素?

示例:

array = [1,2,3,4,5,6,7,8,9,10];

提取5个元素:

extract = [1,3,5,7,10];

4 个答案:

答案 0 :(得分:3)

喜欢这个吗?

/**
 * Retrieve a fixed number of elements from an array, evenly distributed but
 * always including the first and last elements.
 *
 * @param   {Array} items - The array to operate on
 * @param   {Number} n - The number of elements to extract
 * @returns {Array}
 */
function distributedCopy(items, n) {
    var elements = [items[0]];
    var totalItems = items.length - 2;
    var interval = Math.floor(totalItems/(n - 2));
    for (var i = 1; i < n - 1; i++) {
        elements.push(items[i * interval]);
    }
    elements.push(items[items.length - 1]);
    return elements;
}

示例:

// Set up an array for testing purposes
var items = [];
for (var i=1; i<= 1800; i++) {
    items.push(i);
}

var extracted = distributedCopy(items, 256);

console.log(extracted);

答案 1 :(得分:3)

我以前的回答略有改善

function evenlyPickItemsFromArray<T>(allItems: T[], neededCount: number) {
  // if we want more items than avaliable, return all items
  if (neededCount >= allItems.length) {
      return [...allItems];
  }
  // buffer for collecting picked items
  const result: T[] = [];
  const totalItems = allItems.length;
  // default interval between items (might be float)
  const interval = totalItems/neededCount;

  for (let i = 0; i < neededCount; i++) {
    // always add half of interval, so 'picking area' is 'aligned' to the center
    // eg evenlyPickItemsFromArray([0...100], 1); // [50] instead of [0]
    const evenIndex = Math.floor(i * interval + interval / 2);

      result.push(allItems[evenIndex]);
  }
  return result;
}

// TESTING

// helper to create 0...n array
function createNLongArray(n: number) {
  return Array.from({length: n}).map((_, i) => i);
}

console.log(evenlyPickItemsFromArray(createNLongArray(100), 20)) // [2, 7, 12, 17, 22, 27, 32, 37, 42, 47, 52, 57, 62, 67, 72, 77, 82, 87, 92, 97]

console.log(evenlyPickItemsFromArray(createNLongArray(200), 3)) // [33, 100, 166]

请注意,它并不是每次都选择第一个/最后一个元素,因为它实际上很复杂-例如。如果我选择1个elem-我应该选择第一个还是最后一个,等等。它只是查找均匀分布并选择它们。仅当您需要输入数组中的所有或几乎所有元素时,才会选择第一和最后一个

答案 2 :(得分:0)

基本答案是写

array.filter(filterFunc)

为参数为filterFunceltindex的每个元素调用array,并且应该返回truefalse取决于您是要过滤还是过滤该元素。

所以你需要写filterFunc。要做到这一点,你必须在脑海中清楚地定义。例如,这是一个根据您要提取的元素数量创建filterFunc的函数:

function makeFilterFunc(howMany) {
  return function filterFunc(elt, idx, arr) {
    return idx === 0         ||       // first element
      idx === arr.length-1     ||       // last element
      idx % Math.floor(arr.length / howMany) === 0;
  };
}

现在

filterFunc = makeFilterFunc(256);
array.filter(filterFunc)

< Array[258]

答案 3 :(得分:0)

@ pie6k算法的视觉演示 https://codepen.io/renderlife/pen/GRoxgZj

HTML

<h2>Original array</h2>
<div class="chart js-chartData"></div>
<h2>Evenly reduced array (saved element is green)</h2>
<div class="chart js-chartResult"></div>

CSS

.chart {
  background: #aaaebc;
  display: flex;
  flex-wrap: wrap;
  padding: 10px;
  margin-bottom: 15px;
}
.chart .bar {
  text-align: center;
  font-size: 10px;
  background: #d5d7de;
  margin: 2px;
  min-width: 5%;
  height: 50px
  display: inline-block;
  color: black;
}
.chart .bar.save {
  background: green;
}

JS / JQuery

elementsInArray = 365
neededCountElementsInArray = 234

function createNLongArray(n) {
  return Array.from({length: n}).map((_, i) => i + 1);
}

function evenlyPickItemsFromArray(allItems, neededCount) {
    if (neededCount >= allItems.length) {
        return [...allItems]
    }

    const result = []
    const totalItems = allItems.length
    const interval = totalItems / neededCount

    for (let i = 0; i < neededCount; i++) {
        const evenIndex = Math.floor(i * interval + interval / 2)
        result.push(allItems[evenIndex])
    }

    return result
}

array = createNLongArray(elementsInArray)
array.map(i => $('.js-chartData').append('<span class="bar">' + i + '</span>'))
elementsSave = evenlyPickItemsFromArray(array, neededCountElementsInArray)
console.log(elementsSave)

array.map(i => {
    if (elementsSave.includes(i)) {
      $('.js-chartResult').append('<span class="bar save">' + i + '</span>')
    } else {
      $('.js-chartResult').append('<span class="bar">' + i + '</span>')
    }    
  }
)