多个输入到一个输出

时间:2014-03-31 05:13:32

标签: javascript algorithm

如何处理多个输入值到一个输出值?

function c(input,val){
    return input.indexOf(val)>-1;   
}

function result(i){
    if(c(i,1) && c(i,2) && c(i,3)){
       return "alpha";
    }else if(c(i,1) && c(i,2) && !c(i,3)){ 
       return "beta";
    }else if(c(i,1) && !c(i,2) && c(i,3)){
       return "gamma";
    }else if(c(i,1) && !c(i,2)){ 
       return "delta";
    }else if(c(i,3)){
       return "theta";
    }
   //..... and so on covering all possible combinations

   return null;
}

result([1,2,3]);     //output : alpha
result([1,3,2]);     //output : alpha
result([1,3,1,1]);   //output : gamma
result([1,2,4]);     //output : beta
result([3]);         //output : theta

数组中的值的数量可以是N,但仅来自一组预定义的值

使用这么多组合的正确方法是什么?

4 个答案:

答案 0 :(得分:0)

如果案例更容易获取,则可以更清楚地组织代码。例如,alpha情况可以通过数组[1,2,3]来表示,该数组将列出代码所依赖的数字和布尔值[true,true,true]的数组,它们将指示相应的数字是否发生或不。检查可以通过以下功能实现。

function check_case(values,bools){
   var Result = true;
   for ( var i = 0; i < values.length; i++ ){
     Result = Result && ( c(values[i]) == bools[i] );
   }
   return Result;
}

这规避了c的结果必须单独否定的条件的制定,这使得它们难以遵循和编辑。

这个想法可以更进一步,通过一系列案例来保存案件的名称。包含上述前两种情况的数组将如下所示。

[
  {
    values: [1,2,3],
    bools:  [true,true,true],
    name:   'alpha'
  },
  {
    values: [1,2,3],
    bools:  [true,true,false],
    name:   'beta'
  }
]

然后代码将遍历此数组,为每个索引调用check_case并为第一个匹配返回name的值。

答案 1 :(得分:0)

让你的预定义数组为: - [3,2,1](为了简单起见我保持简短,这可以扩展到N个元素)

预定义数组作为布尔字符串可以显示为: - 123

您可以将此数字视为布尔值并创建所需的输出映射: -

示例: - 如果没有数字: - 000 0
如果只有1: - 100 4
如果只有1和2: - 110 6

等等所有必需的布尔组合都可以定义

因此,对于N个数字,您可以创建所需的所有可能组合的列表

示例: - var definedSet = {&#34; 0&#34;:&#34; Alpha&#34;,&#34; 1&#34;:&#34; beta&#34;,&#34; 2&#34;:&#34;伽马&#34;&#34; 3&#34;:&#34; X&#34;&#34; 4&#34;:&#34; Y&#34 ;, &#34; 5&#34;:&#34; Z&#34;&#34; 6&#34;:&#34;&#34;&#34; 7&#34;:&#34; b& #34;};

现在接受输入并删除重复项并检查位置(数字的位位置并创建一个布尔值并将其映射到定义的集合)

代码: -

function sortAndRemoveDuplicates(arr) {
    arr.sort( function(a, b) { return a - b; } );
    var copy = arr.slice(0);
    arr.length = 0;

    for (var i = 0, len = copy.length; i < len; ++i) {
        if (i == 0 || copy[i] != copy[i - 1]) {
            arr.push(copy[i]);
        }
    }
    return arr;
}

var definedArr = [3,2,1];
var definedSet = {"0":"Alpha","1":"beta","2":"gama","3":"x","4":"y","5":"z","6":"a","7":"b"};

var inputArr=[1,4,3,1,1];
sortAndRemoveDuplicates(inputArr);

var outBooleanValue = 0;
for(var i=0;i<inputArr.length;i++)
{
    var numIndex =definedArr.indexOf(inputArr[i]); 
    if(numIndex!=-1)
    {
        outBooleanValue+=Math.pow(2,numIndex);         
    }
}

result =definedSet[outBooleanValue.toString()];
alert(result);

这是工作小提琴: -

http://jsfiddle.net/9tFnn/1/

以下是此版本的另一个版本,其中不需要预定义输入,它允许您按照指定提供条件: -

var definedSet = {"1":"alpha","12":"beta","12!3":"gama","123":"delta"};

$("#defined-set").html(JSON.stringify(definedSet));

var inputArr=[1,2];
$("#input").html(JSON.stringify(inputArr));
$.unique(inputArr);
inputArr.sort();
var outputStr = inputArr.join('');
var regexStr = '';
var loopCounter=0;
for(loopCounter=0;loopCounter<outputStr.length;loopCounter++)
    regexStr+='(!\\d)*'+outputStr[loopCounter]+'(!\\d)*';

regexStr+='$';

//var regexPattern = new RegExp(regexStr);

console.log(regexStr);

for(var currSet in definedSet)
{
     //var match = regexPattern.test(currSet);
    var match = currSet.search(regexStr);  
    if(match!=-1)
    {
         if(currSet==outputStr)
        {
            $("#result").append("Exact Match::");    
        }
        $("#result").append(currSet+"<br/>");
    }



}

以下是工作小提琴的链接: -

http://jsfiddle.net/hLUuF/1/

注意: - 这只是用于获得答案的算法的基本原型,可以根据编程需要进行修改。

希望这证明是有用的。

答案 2 :(得分:0)

根据Condor的回答,以下内容应该可以胜任。它使用一系列测试来计算结果,并实现“非”测试。如果值为“true”,则必须出现,如果值为“false”,则不得出现。如果没有提及,那么它是否在值中无关紧要。

重复不是问题,在一个失败之前处理值。首先删除重复项可能会加快它的速度。

结果是第一组测试的名称。

function testValues(values) {

  var checks = [
      {alpha:  {1:true,  2:true,  3:true }},
      {beta :  {1:true,  2:true,  3:false}},
      {gamma:  {1:true,  2:false, 3:true }},
      {theta:  {3:true}}
  ];
  var check, resultName, tests, passed;

  // Do checks in sequence
  for (var i=0, iLen=checks.length; i<iLen; i++) {
    check = checks[i]

    // Get name of result to return if the checks pass
    for (resultName in check) {

      // Make sure result is own property
      if (check.hasOwnProperty(resultName)) {

        // Passed is true until a fail is found
        passed = true;

        // Get tests to perform
        tests = check[resultName];

        // For each value in tests, make sure value exists or doesn't in values
        for (var v in tests) {

          if (tests.hasOwnProperty(v)) {

            // Only test if passed is true
            if (passed) {

              // Note that indexOf uses === so must have same type
              // Property names are always strings so if passing numbers,
              // Must convert to numbers
              passed = tests[v] === (values.indexOf(+v) != -1);
            }
          }
        }

        // If passed tests, return
        if (passed) return resultName;

      }
    }
  }
  return 'failed all tests...';
}

console.log(testValues([1,2,3]));     //output : alpha
console.log(testValues([1,3,2]));     //output : alpha
console.log(testValues([1,3,1,1]));   //output : gamma
console.log(testValues([1,2,4]));     //output : beta
console.log(testValues([3]));         //output : theta

如果 Object.keys forEach 一起使用,代码可能会更短一些,但上面的内容更清晰一点(可能),它可以重构为短。如果提供 Array.prototype.indexOf 的垫片,上述内容将适用于ECMA-262 ed 3环境。

修改

如果使用现代功能,可以简化代码。为旧版浏览器提供支持并不困难:

// These are sufficient to support the function but are not suitable for general use
// Better versions are avaialble at MDN, see links below
if (!Object.keys) {
  Object.keys = function(obj) {
    var keys = [];
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        keys.push(key);
      }
    }
    return keys;
  };
}

if (!Array.prototype.indeOf) {
  Array.prototype.indexOf = function (value) {
    for (var i=0, iLen=this.length; i<iLen; i++) {
      if (this[i] === value) return i;
    }
    return -1;
  };
}

function testValues(values) {

  var checks = [
      {alpha:  {1:true,  2:true,  3:true }},
      {beta :  {1:true,  2:true,  3:false}},
      {gamma:  {1:true,  2:false, 3:true }},
      {theta:  {3:true}}
  ];
  var check, passed, resultName, tests, testKeys;

  for (var i=0, iLen=checks.length; i<iLen; i++) {
    check = checks[i]
    resultName = Object.keys(check)[0];
    passed = true;
    tests = check[resultName];
    testKeys = Object.keys(tests);

    for (var j=0, jLen=testKeys.length; j<jLen && passed; j++) {
      passed = tests[testKeys[j]] === (values.indexOf(+testKeys[j]) != -1);
    }

    if (passed) return resultName;
  }
  return 'failed all tests...';
}

Object.keys:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

Array.prototype.indexOf:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf

答案 3 :(得分:0)

此解决方案假定输入中元素的顺序并不重要。也就是说,[1, 3, 2]的输入与[1, 2, 3]的输入相同。

看起来你要做的就是从范围(1..n)中获取一组可能的输入,每个输入可能存在也可能不存在。换句话说,对于范围[1, 2, 3, 4],一个可能的输入将是[1, 3]。或者,

Out of:  [1, 2, 3, 4]
We want: [x, 0, x, 0]

这看起来很像二进制数,特别是如果我们颠倒了订单。所以我们真正需要做的就是

  1. 将输入转换为二进制数
  2. 使用该二进制数作为预定义值查找表的索引
  3. 对于第一部分,我们需要做的是循环输入值和OR相应的位。这也会自动处理任何重复。

    for (i=0;i<input_array.length;i++)
    {
        num = num | (1 << (input_array[i] - 1));
    }
    

    - 1因为我们的序列是从1而不是0开始的。因此,4的输入将生成10002的输入将生成0010OR - 将它们放在一起会给我们1010或10(十进制)。

    现在num包含我们预先设置的表的索引:

    values[0] = "alpha";   // Corresponding to input []
    values[1] = "beta";    // Corresponding to input [1]
    ...
    values[10] = "gamma";  // Corresponding to input [4, 2] - remember, it's reversed
    ...
    values[15] = "theta";  // Corresponding to input [4, 3, 2, 1]