排序数组交替数据

时间:2015-10-19 20:14:12

标签: javascript sorting

给定一个数组,我需要重新排列元素,以便没有两个相邻的元素是相同的。排序无关紧要。

var list = ['a','c','c','a','b','b'];

//expected ['a','c','a','b','c','b'];

var listb = ['a','c','c','c','c','a'];

//expected ['a','c','a','c','c','c'];

规则是:下一项永远不应该等于前一项。

更新

更多规则:

  • 第一项永远不应该被触及,保持
  • 其余的等于物品应该在最后

5 个答案:

答案 0 :(得分:2)

这看起来像一个有趣的问题。

所以如果我没有弄错的话,那就是规则:

  1. 下一项永远不应该与之前的
  2. 相等
  3. 第一项永远不应该被触及,保持
  4. 它应该是交替的,字母顺序并不关心
  5. 其余的等于物品应该在最后
  6. 我采取了递归方法。 也许这就是你要找的东西?

      

    结果如下:

         

    [' A'' C'' C'' A'' B',& #39; b'] => [' a'''' c',''' a',' C&#39]

         

    [' A'' C'' C'' C'' C',& #39; a'] => [' a'' c',' a',' c'' c',' C&#39]

         

    [' a',' a'' b',' a'] => [' a',' b',' a',' a']

    
    
    function alternateArray(originalArray) {
      var resultArray = [];
      var allValuesSame = function(myArray) {
        for (var p = 0; p< myArray.length; p++) {
          if (myArray[0] != myArray[p]) {
            return false;
          }
        }
        return true;
      };
      var process = function (originalArray, resultArray) {
        if (originalArray.length == 0) {
          return resultArray;
        }
        // Find a suitable spot that would respect the alternating requirement
        for (var i = originalArray.length -1; i>=0; i--) {
          var replaced = false;
          for (var j = 1; j<resultArray.length-1; j++) {
            if (resultArray[j] && resultArray[j+1]) {
              if (resultArray[j] != originalArray[i] && resultArray[j+1] != originalArray[i]) {
                resultArray.splice(j+1, 0, originalArray.splice(i, 1)[0]);
                replaced = true;
                break;
              }
            }
          }
          if (replaced) {
            continue;
          }
          // If no suitable spot was found, lets try the end of the resultArray
          if (resultArray[resultArray.length-1] != originalArray[i]) {
            resultArray.push(originalArray.splice(i, 1)[0]);
            continue;
          }
          if (allValuesSame(originalArray) && originalArray.length > 0) {
            // Rule: the rest of equals items should be at the end
            for (var z = 0; z < originalArray.length; z++) {
              resultArray.push(originalArray[i]);
            }
            return resultArray;
          }
        }
    
        return process(originalArray, resultArray)
      };
      // Rule: keep the first item (Rule)
      if (originalArray[0]) {
        resultArray.push(originalArray.splice(0, 1)[0]);
      }
      return process(originalArray, resultArray);
    }
    
    console.log(alternateArray(['a','c','c','a','b','b']));
    console.log(alternateArray(['a','c','c','c','c','a']));
    console.log(alternateArray(['a', 'a', 'b', 'a']));
    &#13;
    <script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:0)

在这里你修改了Durstenfeld shuffle算法:

function shuffleArray(array) {
    for (var i = array.length - 1; i > 0; i--) {
        var j;
        var count = 0;
        do {
            j = Math.floor(Math.random() * (i + 1));
            count++;
        } while(i!=array.length && array[i+1] == array[j] && count < 500);

        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    return array;
}

这里唯一可以出现的是第一个字母可能等于第二个字母。但它很容易检查和修复。

以上问题已修复:https://jsfiddle.net/1zeafb31/

(function() {
    var list = ['a','c','c','a','b','b'];
    var sortedList = list.sort();

    var shuffleArray = function(array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j;
            var count = 0;
            do {
                j = Math.floor(Math.random() * (i + 1));
                count++;
            } while(i!=array.length && array[i+1] == array[j] && count < 500);

            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        if(array.length > 1 && array[0] == array[1]) {
            var temp = array[0];
            array[0] = array[array.length - 1];
            array[array.length-1] = temp;
        }
        return array;
    }
    
    document.getElementById('randomize').onclick = function(e) {
        document.getElementById('result').innerHTML = shuffleArray(list).join(' ');
    };
    
})();
<div id='result'></div>

<br>
    <button id='randomize'>Randomize</button>

答案 2 :(得分:0)

另一种方法是构建一个列表,用于计算输入字符串中每个字符的出现次数,按字符代码对此出现列表进行排序,并通过迭代事件列表生成一个与输入字符串长度相同的新字符串。 / p>

function shuffle(src) {
  if ('string' != typeof src) {
    throw new Error('Invalid source string.');
  }

  if (src.length < 3) {
    return src;
  }

  var countersByChar = {};
  var countersList = [];

  // STEP 1: Count each character occurrence.
  for (var i = 0; i < src.length; ++i) {
    var chr = src[i];
    var counter = countersByChar[chr];

    if (!counter) {
      counter = {
        chr: chr,
        count: 0
      };

      countersByChar[chr] = counter;
      countersList.push(counter);
    }

    ++counter.count;
  }

  // STEP 2: Sort counters list by character code.
  countersList.sort(function(lhs, rhs) {
    return lhs.chr.charCodeAt(0) - rhs.chr.charCodeAt(0);
  });

  // STEP 3: Generate a new permutation.
  var charsLeft = src.length;
  var p = 0;
  var dest = [];

  while(charsLeft) {
    var c = countersList[p];
    dest.push(c.chr);

    if (!--c.count) {
      countersList.splice(p, 1);
    } else {
      ++p;
    }

    if (p == countersList.length) {
      p = 0;
    }

    --charsLeft;
  }

  var result = dest.join('');
  return result;
}

function test(src) {
  alert('shuffle("' + src + '") => ' + shuffle(src));
}

test('accabb');
test('acccca');

以下是工作示例:https://jsfiddle.net/pbcq2o3y/

&#13;
&#13;
    function shuffle(src) {
      if ('string' != typeof src) {
        throw new Error('Invalid source string.');
      }

      if (src.length < 3) {
        return src;
      }

      var countersByChar = {};
      var countersList = [];

      // STEP 1: Count each character occurrence.
      for (var i = 0; i < src.length; ++i) {
        var chr = src[i];
        var counter = countersByChar[chr];

        if (!counter) {
          counter = {
            chr: chr,
            count: 0
          };

          countersByChar[chr] = counter;
          countersList.push(counter);
        }

        ++counter.count;
      }

      // STEP 2: Sort counters list by character code.
      countersList.sort(function(lhs, rhs) {
        return lhs.chr.charCodeAt(0) - rhs.chr.charCodeAt(0);
      });

      // STEP 3: Generate a new permutation.
      var charsLeft = src.length;
      var p = 0;
      var dest = [];

      while(charsLeft) {
        var c = countersList[p];
        dest.push(c.chr);

        if (!--c.count) {
          countersList.splice(p, 1);
        } else {
          ++p;
        }

        if (p == countersList.length) {
          p = 0;
        }

        --charsLeft;
      }

      var result = dest.join('');
      return result;
    }

    function test(src) {
      alert('shuffle("' + src + '") => ' + shuffle(src));
    }

    test('accabb');
    test('acccca');
&#13;
&#13;
&#13;

答案 3 :(得分:0)

编辑 此答案发布后,此答案不会处理问题中添加的两条规则。

这是一个天真的答案,我不知道性能,效率或优化,但这可以做到这一点。

对于一个用例,它不符合您的期望:

给定数组:["a","c","c","c","c","a"]
expected-&GT; :["a","c","a","c","c","c"]
结果 - - - &gt; :["c","a","c","c","a","c"]

我认为预期不尊重您提供的唯一规则:

  

下一项 从不 应该等于之前的

但结果更尊重规则!

我希望这会对你有帮助。

/* debug purpose */
var el = document.getElementById('el');
var j = JSON.stringify;

var log = function(val) {
  console.log(val);
  el.innerHTML += '<div><pre>' + val + '</pre></div>'
};

var tmpl = function(argList, argResult, argExpected){
  log( j(argList)  + '\n\t become\n' + j(argResult) +
    "\n\texpected\n" + j(argExpected) + 
    " matching : " + 
    (j(argResult) === j(argExpected) ) 
  );

};

/* Main function */
var Alternate = function(listToAlternate) {

  var clone = listToAlternate.slice(0);

  var nextNot = function(val, from, arr) {
    var idx = from + 1;
    for ( idx; idx <= arr.length ; idx++ ) {
      if (arr[ idx ] != val && arr[ idx + 1 ] != val) return idx;
    }
    return from;
  };
  
  var prevNot = function(val, from, arr) {
    var idx = from - 1;
    for ( idx; idx >= 0; idx-- ) {
      if ( arr[ idx ] != val && arr[ idx - 1 ] != val) return idx;
    }
    return from;
  };  
 
  
  var len = clone.length;
  
  var prev = '';
  var curPos;
  var curVal;
  var repetition;
  
  for( var i = 0 ; i < len ; i++){
    
    curPos = i;
    curVal = clone[ curPos ];
    
    if(curVal == prev){
  
      repetition = clone.splice( curPos , 1)[0];// remove
      
      var nextPos; 
      if(curPos === len){
        nextPos = prevNot(repetition , curPos , clone);// lookFor
      } else {
        nextPos = nextNot(repetition , curPos , clone);// lookFor
      }
      
      clone.splice(nextPos , 0 , repetition); //insert
    }
  
    prev = clone[i];
  };

  prev = '';
  curVal = undefined;
  curPos = undefined;
  repetition = undefined;
  
  for( var i = len-1 ; i>=0  ; i--){
    curPos = i;
    curVal = clone[ curPos ]
    
    if(curVal == prev){
      
      repetition = clone.splice( curPos , 1)[0]; // remove
      var prevPos = prevNot(repetition , curPos , clone); // lookFor
      clone.splice(prevPos , 0 , repetition); // insert
      
    }
  
    prev = clone[i];
  };

  return clone;
};




/* Use case testing */
var list;
var expected;



list     = ['a','c','c','a','b','b'];
expected = ['a','c','a','b','c','b'];
result   = Alternate( list );

tmpl( list , result , expected);


list = ['a','b','b','a'];
expected = ["a","b","a","b"];
result   = Alternate( list );

tmpl( list , result , expected);


list = ['a','a','b','a'];
expected = ["a","b","a","a"];
result   = Alternate( list );

tmpl( list , result , expected);


list = ['a','c','c','c','c','a'];
expected = ['a','c','a','c','c','c'];
result   = Alternate( list );

tmpl( list , result , expected);


list = ['hello','hello', 'bye','bye','hello'];
expected = ['hello','bye','hello','bye','hello'];
result   = Alternate( list );

tmpl( list , result , expected);


list = ['b','b','b','b','a','c','c','a','b','b','b'];
result   = Alternate( list );

log( j( list ) + '\n\t become\n' + j( result ) );


list = ['a','c','c','c','a','b','b','z'];
result   = Alternate( list );

log( j( list ) + '\n\t become\n' + j( result ) );
div{
  border : solid 1px #EEE;
  }
<div id='el'></div>

答案 4 :(得分:-1)

好的,我找到了一个解决方案并按预期工作

var alternate = function(list) {
    var index = 0;
    var list_size = list.length;
    var process = function(list_process) {

        // Search the next item different, remove and return this.
        var serchNextDifferent = function(number) {
            for (var i = index+1; i <= list_size; i++) {
                if (list_process[i] !== number) {
                    return list_process.splice(i,1)[0];
                }
            }
        };
        // Search the next item different, remove and return this.
        var serchPrevDifferent = function(number, index) {
            for (var i = index-1; i >= 0; i--) {
                if (list_process[i] !== number && list_process[i] !== list_process[index] && number !== list_process[i-1] && i) {
                    return list_process.splice(i,1)[0];
                }
            }
        };
        // Check if the current item and the prev are equals
        if (list_process[index-1] === list_process[index]) {
            var next = serchNextDifferent(list_process[index]);
            if (next) {
                list_process.splice(index, 0, next[0]);
            } else {
                var prev = serchPrevDifferent(list_process[index], index);
                if (prev) {
                    list_process.splice(index-1, 0, prev[0]);
                } else {
                    list_process.push(list_process.splice(index, 1)[0]);    
                }
            }
        }

        // next
        if (list_size-1 !== index) {
            index++;
            return process(list_process);
        } else {
            return list_process; 
        }
    };
    return process(list);
};

以下是工作示例Link