haizlin/fe-interview

[js] 第24天 如何快速让一个数组乱序,写出来

haizhilin2013 opened this issue · 33 comments

第24天 如何快速让一个数组乱序,写出来

直接使用原生的sort()方法:

var arr= [1,2,3,4,5]
arr.sort(function(a,b){return Math.random() > 0.5 ? 1 : -1})
console.log(arr);// [ 1, 3, 5, 2, 4 ]

使用array.sort()进行乱序存在一定问题,增大样本进行实验之后可以发现这种乱序方案并不是完全随机的(所有元素会大概率停留在自己的初始位置)(v8处理排序是小于10个是插入排序,大于10个是快排,排序算法复杂度介于O(n)与O(n2)之间,也就是存在两个元素都没有比较的机会,因此不是完全随机),这里可以使用Fisher–Yates shuffle(洗牌算法)
Array.prototype.shuffle = function() { var input = this; for (var i = input.length-1; i >=0; i--) { var randomIndex = Math.floor(Math.random()*(i+1)); var itemAtIndex = input[randomIndex]; input[randomIndex] = input[i]; input[i] = itemAtIndex; } return input; } var tempArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] tempArray.shuffle(); console.log(tempArray);

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const map = new Map();
arr = arr.map(v => {
const random = Math.random();
map.set(random, v);
return random
}) //arr 替换成随机数, 原数组成员存入map
.sort((a, b) => a - b) //排序随机数
.map(v => map.get(v)); //取出数组成员填入数组

console.log(arr);

arr.sort(function(a,b){ return Math.random()>.5 ? -1 : 1;});

let arr= [1,2,3,4,5,6,7,8,9,10];
arr.map((item,index)=>{
    let random =Math.floor(Math.random() * arr.length);
    [arr[index],arr[random]] = [arr[random],arr[index]];
});
console.log(arr);

为什么楼上要用三元运算符,直接这样不就完事了。。

arr.sort((a, b) => Math.random() - .5)

不过我们team随机算法也用的洗牌算法,思路就是从后往前遍历,然后随机(0, i+1),交换

function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    let j = Math.floor(Math.random() * (i + 1))
    [array[i], array[j]] = [array[j], array[i]]
  }
}
function mixi(arr){
  arr.sort(function(a,b){
   (Math,random()>0.5)?a-b>0:a-b<0
 })
}
const swap = (arr, index1, index2) => {
  ;[arr[index1], arr[index2]] = [arr[index2], arr[index1]]
}

export default function shuffle(arr = []) {
  if (!Array.isArray(arr)) return
  let index = arr.length - 1
  for (; index > 0; index++) {
    const randomIndex = Math.floor(Math.random() * (index + 1))
    swap(arr, index, randomIndex)
  }
}

前面有些, 为啥发之前不先测试下...
加个判断吧.

function shuffle (arr) {
  for (let i = 0, len = arr.length; i < len; i++) {
    let j = Math.floor(Math.random() * len)
    if (i !== j) [arr[i], arr[j]] = [arr[j], arr[i]]
  }
  return arr
}

console.log(shuffle([1,2,3,4,5,6,7,8,9,0]))

image

const shuffle = arr => arr.sort(() => Math.random() - 0.5);

//洗牌数组
export function shuffle(arr) {
const _arr = arr.slice();
for (let i = 0; i < _arr.length; i++) {
//调用
let j = getRandomNumber(0, i);
let t = _arr[i];
_arr[i] = _arr[j];
_arr[j] = t;
}
return _arr;
}

//随机取0-1中间值(包括0和1)
export function getRandomNumber(min, max) {
return Math.floor(Math.random() * (max - min + 1));
}

使用array.sort()进行乱序存在一定问题,增大样本进行实验之后可以发现这种乱序方案并不是完全随机的(所有元素会大概率停留在自己的初始位置)(v8处理排序是小于10个是插入排序,大于10个是快排,排序算法复杂度介于O(n)与O(n2)之间,也就是存在两个元素都没有比较的机会,因此不是完全随机),这里可以使用Fisher–Yates shuffle(洗牌算法)
Array.prototype.shuffle = function() { var input = this; for (var i = input.length-1; i >=0; i--) { var randomIndex = Math.floor(Math.random()*(i+1)); var itemAtIndex = input[randomIndex]; input[randomIndex] = input[i]; input[i] = itemAtIndex; } return input; } var tempArray = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] tempArray.shuffle(); console.log(tempArray);

大神,想问下,arr.sort(function(a,b){return Math.random() > 0.5 ? 1 : -1}),这种呢随机不是和Math.random的值密切相关吗,和sort有关系么?我的理解是sort是按照Math.random来排序,Math.random是完全随机的吧,那么这个整体应该也是完全随机的吧

function mess(arr){
let index
let i = 0
let newArr = []
arr = arr.concat()
while(arr.length){
let index = parseInt(Math.random()* (arr.length))
newArr[i] = arr[index]
arr.splice(index, 1)
i++
}
return newArr
}
image

var arr= [1,2,3,4,5]
arr.sort(function(a,b){
return Math.random() > 0.5 ? 1 : -1 // 判断随机数
})
console.log(arr);
const shuffle = ([...arr]) => {
    let m = arr.length;
    while (m) {
      const i = Math.floor(Math.random() * m--);
      [arr[m], arr[i]] = [arr[i], arr[m]];
    }
    return arr;
};
  
const foo = [1, 2, 3];
console.log(shuffle(foo))
function messArr(arr) {
  let newIndex = [];
  let newArr = [];
  while (newIndex.length < arr.length) {
    let num = Math.floor(Math.random() * arr.length);
    if (!newIndex.includes(num)) {
      newIndex.push(num);
    }
  }
  for (let index in newIndex) {
    newArr.push(arr[newIndex[index]]);
  }
  return newArr
}
var arr = ['广西', '上海', '北京', '云南'];
console.log(messArr(arr));
rni-l commented
function shuffle(array) {
  let _array = array.map(v => v)
  return array.reduce((acc, cur, curIndex, arr) => {
    // 取 [0, 数组长度 - 1] 的随机数
    const randomVal = Math.floor(Math.random() * _array.length)
    acc.push(
      _array[randomVal]
    )
    // 删除对应的数
    _array.splice(randomVal, 1)
    return acc
  }, [])
}

console.log(randomArray([0,1,2,3,4,5]))
0x3c commented
/**
 * @param {number[]} arr
 * @return {number[]}
 */
function shuffle(arr) {
  arr.sort(() => Math.random() - 0.5);
}

shuffle的**·

 const randomSort = (arr=[]) => {
    const length = arr.length;
    for(let index = 0; index < length; index++) {
       let randomIndex = Math.floor(Math.random()*(length - index)) + index;
        [arr[index], arr[randomIndex]] = [arr[randomIndex], arr[index]]
    }
    return arr;
}
    Array.prototype.shuffle = function () {
      let _this = this
      for(let i = _this.length - 1; i >= 0; i--){
        let randomIndex = Math.floor(Math.random() * (_this.length - 1))
        let temp = _this[randomIndex]
        _this[randomIndex] = _this[i]
        _this[i] = temp
      }
      return _this
    }
    var tempArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    tempArray.shuffle();
    console.log(tempArray);

照着上面的大佬敲了一遍,感觉randomIndex这里一直用数组的长度-1会不会好一点啊

function fn(arr) {
            var newarr = arr.concat();
            for (var i = 0; i < newarr.length; i++) {
                var index = Math.floor(Math.random() * newarr.length);
                var temp = newarr[i];
                newarr[i] = newarr[index];
                newarr[index] = temp;
            }
            return newarr;
        }

第24天 如何快速让一个数组乱序,写出来


function outOfOrder(arr) {
    return arr.sort(function(){ return Math.random() < 0.5 ? 1 : -1 })
}

console.log(outOfOrder([1,2,3,4,5]))

function outOfOrder(arr) {
return arr.sort(function(){ return Math.random() < 0.5 ? 1 : -1 })
}

console.log(outOfOrder([1,2,3,4,5]))

/**

  • 如何快速让一个数组乱序,写出来
    */
    function randomSortArr(arr){
    const newArr = [];
    function recursive(){
    const len = arr.length;
    if( arr.length > 0 ){
    const randomNum = parseInt( Math.random() * len );
    newArr.push( arr[randomNum] );
    arr.splice( randomNum,1 );
    recursive();
    }
    }
    recursive();
    return newArr;
    }

console.log( randomSortArr([1,2,3,4,5,6,7,8,9,10,11,12,13,34]) )

function shuffle(arr){
  return arr.sort(() => {
    return Math.random() - 0.5
  })
}

function shuffle2(arr){
  const a = [...arr]
  const res = []

  while (a.length) {
    const idx = Math.floor(Math.random() * a.length)

    res.push(...a.splice(idx, 1))
  }

  return res
}

const arr = [1,2,3,4,5,6,7,8]

console.log(shuffle(arr))
console.log(shuffle2(arr))

// [ 7, 2, 1, 5, 6, 4, 3, 8 ]
// [ 2, 8, 1, 5, 3, 6, 4, 7 ]

function rd(arrayLength) {
return Math.floor(Math.random() * arrayLength);
}
//The Math.random() function returns a floating-point, pseudo-random number in the range 0 to less than 1 (inclusive of 0, but //not 1)...

const result=[];
var count=0;
function recur(pArray){
console.log(pArray);
if(result.length===pArray.length){
return ;
}

count++;
let k=rd( pArray.length );

if(pArray[k] !==null){
result.push(pArray[k]);
pArray[k] =null;
}
recur(pArray);
}
recur(arr);
console.log(count);
console.log(result );

sort()

// ES5
function randArr(arr) {
    return arr.sort(function () {
        return Math.random() - 0.5;
    });
}
console.log(randArr([1, 2, 3, 4, 5]));

// ES6
let arr = [1, 2, 3, 4, 5];
let newArr = (arr) => arr.sort(() => Math.random() - 0.5);
console.log(newArr(arr));

let arr = [1, 2, 3, 4, 5];
let newArr = arr.sort(() => Math.random() - 0.5);
console.log(newArr);

const shuffle = arr => arr.sort(() => Math.random() - 0.5);

var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(array.sort((a, b) => {
return Math.floor(Math.random() * 10) - 5;
}));

let arr6 = [1,2,3,4,5,6,7,8,9]
// 将数组乱序
function shuffle(arr) {
// 第一种 sort
// return arr.sort(() => Math.random() - 0.5)
// 第二种 洗牌
for(let i=0, len = arr.length; i<len; i++) {
let k = Math.floor(Math.random() * len)
// 交换元素
if (k != i) [arr[k], arr[i]] = [arr[i], arr[k]]
}
return arr
}
console.log(shuffle(arr6))

wenxd commented
  let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  let newArr = []
  for (i = 0; i < arr.length; i < 10) {
    let index = Math.floor(Math.random() * arr.length)
    let item = arr.splice(index, 1)[0];
    newArr.push(item);
  }
  console.log(newArr)
wyy-g commented

洗牌算法(shuffle):假设数组长度为n,生成0 ~ n-1之间的随机数random,然后将第random个元素与最后一个元素交换位置,继续生成 0 ~ n-2 之间的随机数random,将第random个元素与数组倒数第二个元素交换位置

function shuffle(arr){
let len = arr.length;
for(let i = len - 1; i > 0; i --){
let random = Math.floor(Math.random() * (i + 1));
[arr[random], arr[i]] = [arr[i], arr[random]];
}
return arr;
}

在JavaScript中,可以使用洗牌算法(Fisher-Yates算法)来快速将一个数组乱序。以下是一个实现洗牌算法的示例:

function shuffleArray(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1)); // 生成一个随机索引
    [array[i], array[j]] = [array[j], array[i]]; // 交换当前位置和随机位置的元素
  }
  return array;
}

// 示例用法
const myArray = [1, 2, 3, 4, 5];
const shuffledArray = shuffleArray(myArray);
console.log(shuffledArray); // 输出乱序后的数组

在上面的示例中, shuffleArray 函数接受一个数组作为参数,并使用洗牌算法对数组进行乱序。算法通过从最后一个元素开始,逐步向前遍历数组,每次生成一个随机索引,并将当前位置的元素与随机位置的元素进行交换。最终得到乱序后的数组。

请注意,这个算法会修改原始数组,如果不想修改原始数组,可以在函数内部创建一个新的数组并进行操作。