最小/最大

时间:2018-11-25 00:27:00

标签: javascript arrays node.js

我有一个1,000,000字节的文件。我想以最小和最大块大小随机地分割文件200,000字节,同时确保对所有200,000字节进行分割,而不会低于最小块字节大小。

例如:

const min = 20000, max = 50000
const result = [[0,20000], [25000,50000], [72000,110000], ...]

在过去的半小时内,我一直在努力思考。不能在互联网上找到任何内容。

2 个答案:

答案 0 :(得分:0)

因此,如果我理解正确,则需要检索数据的子集,其中该子集分为最小/最大大小之间的块,并随机选择偏移量和块大小。诀窍在于,您要确保在满足条件之前不会耗尽内存。

首先让我们自己确定块大小。由于min块大小的限制,并且需要精确地求和到某个值,这实际上是一个非常困难的问题。因此,您可以想象有N组可能的块大小来适合所需的总数,其中每个块大小可以是约束范围内的任何值。但是,并非每个集合都包含符合最小/最大约束的块大小。我在下面整理了一个可行的示例,但是请注意,如果发现失败的集合,它会通过重试来蛮力地提供理想的答案。

const randInt = (min,max) => {
  return Math.floor(Math.random() * (max - min + 1) + min)
}

const getSizeArray = (min, max, total) => {
  const output = []
  var leftovers = total
  while(leftovers > max){
    const nextSize = randInt(min, max)
    output.push(nextSize)
    leftovers -= nextSize
  }
  // if the leftovers are less than min, this set is impossible
  if(leftovers < min){ return getSizeArray(min, max, total) }
  // cater to the final amount to get exact size
  if(leftovers > 0){ output.push(leftovers) }
  return output
}

const sizes = getSizeArray(20000, 50000, 200000)
console.log(sizes)

我们在这里所做的就是继续选择该范围内的随机大小,并将最终值作为总约束的差。我不确定这将如何影响分布。


因此,一旦有了块大小,就只需要计算偏移量即可。您可以通过多种方法来执行此操作,但是我在下面的操作中尝试对各个块实施相当均匀的间隙。它的工作原理是将总计的内存除以块的数量,然后找到一个内存范围,每个块可以自由地从中随机选择一个偏移量。例如:

const randInt = (min,max) => {
  return Math.floor(Math.random() * (max - min + 1) + min)
}

const getSizeArray = (min, max, total) => {
  const output = []
  var leftovers = total
  while(leftovers > max){
    const nextSize = randInt(min, max)
    output.push(nextSize)
    leftovers -= nextSize
  }
  // if the leftovers are less than min, this set is impossible
  if(leftovers < min){ return getSizeArray(min, max, total) }
  // cater to the final amount to get exact size
  if(leftovers > 0){ output.push(leftovers) }
  return output
}

const sizes = getSizeArray(20000, 50000, 200000)

const getOffsets = (arr, memSize) => {
  const result = []
  const sum = arr.reduce((r, i) => r + i, 0)
  const gap = (memSize - sum) / arr.length
  arr.forEach((item, i) => {
    const min = arr.reduce((r, a, index) => {
      if(index < i){
        return r + gap + a
      }
      return r
    }, 0)
    const max = min + Math.floor(gap / 2)
    const offset = randInt(min, max)
    result.push([offset, item])    
  })
  return result  
}

const result = getOffsets(sizes, 1000000)
console.log(result)

答案 1 :(得分:0)

只需生成25000到50000之间的随机值,总计为200000:

 const range = (min, max) => min + Math.floor(Math.random() * (max - min));

function sizes(size, min, max) {
  const sizes = [];
  let pos;
  for(pos = 0; pos < size - max;) {
    const curr = pos + range(min, Math.min(max, size - max));
    sizes.push(curr);
    pos += curr;          
  }

  sizes.push(size - pos);
  return sizes;
}

现在生成块大小和块之间的部分大小,然后将它们映射到索引:

const toChunk = range(1000000 - 200000, 1000000), 
  leftOver = 1000000 - toChunk,
  chunkSizes = sizes(toChunk, 25000, 50000),
  spaceSizes = sizes(leftOver, 0, range(10, leftOver)),
  chunks = [];

while(spaceSizes.length > chunkSizes.length + 1)
  spaceSizes.splice(range(0, spaceSizes.length), spaceSizes.pop() + spaceSizes.pop());

let start = 0;
for(const chunkSize of chunkSizes) {
chunks.push([start, start + chunkSize - 1]);
  start += chunkSize;
  start += spaceSizes.pop() || 0;
}