从数组中过滤非"线性",渐进值

时间:2017-06-01 06:38:50

标签: javascript arrays algorithm loops filter

我不确定如何解释这一点,但请耐心等待......

我编写了一个程序,可以创建长度范围为0-4的随机数组,如下所示:[][n][n,n][n,n,n]或{{1 }}

输入将是1-6之间的随机数字,其中输出[n,n,n,n]始终是输入的倍数。例如,输入可能是n,输出可能是2[2][4,8]

输出将始终从最低值到最高值排序。

输入始终是最低倍数,而最高倍数始终是[2,4,6]的值。例如,如果输入为input * 4,则输出范围为3-12或3,6,9和12。

假设,我们说输入是3,而输出(如果有的话)当然是4的倍数。

唯一可能的输出是......

4 [] [4] [8] [12] [16] [4,8] [4,12] [4,16] [8,12] [8,16] [12,16] [4,8,12] [4,8,16] [4,12,16] [8,12,16]

我想要做的是过滤输出,以便只有上面的粗体数组才有效。除此之外,我想保留所有有效的数组元素,同时删除所有非"线性",渐进元素,如下所示:

  • [4,8,12,16]将变为 [4,12]
  • [4]将变为 [4,8,16]
  • [4,8]将变为 [8,16]
  • []将变为 [8,12,16]
  • []将变为 [12,16]

我终于弄清楚我是如何实现这一目标的,但无论出于何种原因我花了一段时间才能绕过它;所以现在我只是超级好奇。有没有另一种方法来实现这个输出,它明显比下面的代码更有效?是否有可能通过某种循环做同样的事情?是否有任何已知的算法可以解决这类问题?

[]

3 个答案:

答案 0 :(得分:2)

因为您的阵列具有固定的长度,所以效率与否并不是真正的问题。

也就是说,可以用更通用的方式编写手工案例区分。这可能会节省一些与数组长度的比较,但最大的好处是它不会硬编码值或假定最大数组长度。

想法。从数组的开头开始,然后,对于每个元素,检查它是否是预期的倍数。如果没有,从那时起切断阵列的其余部分。



function filterMultiples(arr, firstMultiple) {
  let badIndex = arr.findIndex((value, index) =>
    (value !== (index + 1) * firstMultiple)
  );
  if (badIndex < 0) {
    return arr;
  }
  return arr.slice(0, badIndex);
}

function test(arr, firstMultiple = 4) {
  console.log(
    JSON.stringify(arr) + ' is filtered to ' +
    JSON.stringify(filterMultiples(arr, firstMultiple)) +
    ` (multiples of ${firstMultiple})`
  );
}

test([4, 8, 16]); // [4, 8]
test([2]); // []
test([4, 6, 12]); // [4]
test([2, 4, 6, 8, 9], 2); // [2, 4, 6, 8]

// tests from question
test([4,12]); // [4]
test([4,8,16]); // [4,8]
test([8,16]); // []
test([8,12,16]); // []
test([12,16]); // []
&#13;
.as-console-wrapper {
  max-height: 100% !important;
}
&#13;
&#13;
&#13;

上述代码段中的CSS仅用于显示目的,导入部分为filterMultiples

解释。我们find the index的第一个元素不是预期值。如果没有找到这样的元素,则所有值都是预期的,我们返回原始数组。否则,我们只返回数组的slice,但不包括第一个意外值。

替代。如果要修改原始数组,可以按如下方式编写函数。

function filterMultiples(arr, firstMultiple) {
  let badIndex = arr.findIndex((value, index) =>
    (value !== (index + 1) * firstMultiple)
  );
  if (badIndex >= 0) {
    arr.splice(badIndex);
  }
}

此方法使用Array#splice

答案 1 :(得分:2)

由于Array.prototype.filter中的回调可以处理索引参数,因此可以直接使用它来仅返回“正确”的值。指数:

&#13;
&#13;
function filterOnFactor(arr, factor){
	return arr.filter((val,i) => ++i * factor == val);
  } 

//test
for(let arr of [[], [4], [8], [12], [16], [4, 8], [4, 12], [4, 16], [8, 12], [8, 16], [12, 16], [4, 8, 12], [4, 8, 16], [4, 12, 16], [8, 12, 16], [4, 8, 12, 16]]){
	console.log(JSON.stringify(arr), '->', JSON.stringify(filterOnFactor(arr,4)));
}
&#13;
&#13;
&#13;

注意,这仅在源始终是因子的递增多数时才有效,因此[6,8,12]仍会返回[8,12],但根据信息,源始终以递增的数量生成

只是为了好玩,也是使用生成器功能的解决方案(对所有输入都是安全的)

&#13;
&#13;
function* filterOnFactor(arr, factor){
    for(let i=0; i< arr.length; i++){
    	if(arr[i] !== ++i * factor)break;
      yield arr[--i];
    }    	
} 

//test
for(let arr of [[], [4], [8], [12], [16], [4, 8], [4, 12], [4, 16], [8, 12], [8, 16], [12, 16], [4, 8, 12], [4, 8, 16], [4, 12, 16], [8, 12, 16], [4, 8, 12, 16], [6,8,12]]){
	console.log(JSON.stringify(arr), '->', JSON.stringify([...filterOnFactor(arr,4)]));
}
&#13;
&#13;
&#13;

答案 2 :(得分:1)

您可以过滤值,然后过滤数组。

function sequence() {
    var i = 1;
    return function (b) {
        return b === factor * i++;
    };
}

function validate(a) {
    return a.filter(sequence());
}

function notEmpty(a) {
    return a.length;
}

var data = [[], [4], [8], [12], [16], [4, 8], [4, 12], [4, 16], [8, 12], [8, 16], [12, 16], [4, 8, 12], [4, 8, 16], [4, 12, 16], [8, 12, 16], [4, 8, 12, 16]],
    factor = 4,
    result = data
        .map(validate)
        .filter(notEmpty);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }