V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
slucus
V2EX  ›  问与答

数组取随机数( 2 或 3 个),取到的数据上下左右不相邻?

  •  
  •   slucus · 2017-05-30 08:54:59 +08:00 · 2439 次点击
    这是一个创建于 2733 天前的主题,其中的信息可能已经有所发展或是发生改变。

    rt

    var a = [
      [0, 1],
      [2, 3],
      [4, 5],
      [6, 7]
    ];
    
    23 条回复    2017-05-30 22:52:15 +08:00
    oott123
        1
    oott123  
       2017-05-30 09:37:35 +08:00 via Android
    看了你昨天的帖子,codehz 提供的方法其实不错。先把符合你要求的数据都拎出来再随机。
    不要说 low,因为你要求的随机并不是真的随机…

    建议把数组拍平,然后上下相邻就是下标差 2,左右相邻就是下标差 1,这样比较好考虑。
    slucus
        2
    slucus  
    OP
       2017-05-30 09:53:09 +08:00
    @oott123
    codehz 提供的是最简单粗暴的,但不实用啊(只适用少量数据)。。
    我只是写出来 4 组数据,那如果有 10 组呢,所以把所有的可能写出来不太实际。。。

    所以我现在使用的方法就是有几组数据就取几个数值,然后再把这些数值装进一个数组里进行随机,但是一直觉得这不是我想要的方法,所以一直到处提问╮(╯▽╰)╭,想看看有没有更优的方案。。

    然后 low (只是想表示复杂的意思,没别的意思- -!)
    blankme
        3
    blankme  
       2017-05-30 09:54:57 +08:00 via Android
    你的题目里说,取 2-3 个数,你昨天的最后回复中提到了“只能取到两组数”,而这两组数都是 4 个。

    请首先确保你的题目描述清晰且正确,推荐你看这篇文章: https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md

    最后,关于带有条件限制的随机选取,一个常用的方法是:

    选取一个,判断是否符合条件。
    符合则保留,不符合则舍弃,再次选取。
    直到获得所需数量的数字。
    zhuzhuyule
        4
    zhuzhuyule  
       2017-05-30 10:04:06 +08:00
    1. 随机获取到 `r=0` or `r= 1`;

    2.取出符合 限制条件 数据
    ```
    var b[4];
    for ( i = 0 ; i < a.length -1 ; i++)
    {
    //取出奇偶数行,与 ①中的 r 做差值 取绝对值
    b[i] = a[i][ abs(i %2 - r) ];
    }
    ```
    3.再从数组`b`中随机取出 2,3 个数 就可以了
    slucus
        5
    slucus  
    OP
       2017-05-30 10:04:49 +08:00
    @blankme
    首先感谢你百忙之中来帮助我,然后关于我昨天的最后回复中提到了“只能取到两组数”,是在运行帖子里的代码以后得出的结果,然后我觉得我的题目还是挺清晰的。。。

    最后关于昨天帖子里的那段代码,又有了一种更优的方案

    %2

    这样只要两行代码就能实现昨天的效果了。。。
    slucus
        6
    slucus  
    OP
       2017-05-30 10:06:29 +08:00
    @zhuzhuyule
    哈哈,我也刚找到这种方法,谢谢!

    共享出来给大家

    var a = [
    [0, 1],
    [2, 3],
    [4, 5],
    [6, 7]
    ];

    function select() {
    var random = Math.round(Math.random());
    for (var i = 0; i < a.length; i++) {
    console.log(a[i][(i + Math.round(Math.random())) % 2]);
    }
    }
    select()
    zhuzhuyule
        7
    zhuzhuyule  
       2017-05-30 10:12:22 +08:00
    @slucus 我现想的,就看下自己老了么 [抠鼻]
    slucus
        8
    slucus  
    OP
       2017-05-30 10:14:34 +08:00
    @zhuzhuyule 没老,依然那么 6
    blankme
        9
    blankme  
       2017-05-30 10:21:02 +08:00 via Android
    @slucus 你和 zhuzhu 的算法不一样的好吗。。你仔细看看,你的代码会得到不符合条件的结果。

    而且 zhuzhu 的算法是得不到(0, 6)这组数的
    Xs0ul
        10
    Xs0ul  
       2017-05-30 10:24:50 +08:00
    @slucus #8 所以二位的方法是,类似奇数行取左,偶数行取右(左右由随机数决定)这样来强制满足要求?

    但是这样是不会同时取到 0 和 6 的,感觉和一般理解的随机不太一致。
    slucus
        11
    slucus  
    OP
       2017-05-30 10:26:50 +08:00
    @blankme 对呀,这依然不是我想要的结果啊,但是至少使用 % 把之前那一长串代码给优化了,具体使用还是要进行改造的,嘿嘿
    slucus
        12
    slucus  
    OP
       2017-05-30 10:31:27 +08:00
    @Xs0ul 对的,这并不是理想的方法,目前我只能做到交叉取数据(达到上下左右不相邻),然后在取到的结果进行随机,然后 0 和 6 的问题还需要继续研究,现在只有一个最粗暴的方法,就是每取到一个数就去做对比,但这样的方法明显是不可取的。。。所以还需要再好好想想
    Xs0ul
        13
    Xs0ul  
       2017-05-30 10:37:09 +08:00
    @slucus #12 如果数据量稍微大一点,其实取到相邻的概率是很低的,所以比较不见得不可取。
    slucus
        14
    slucus  
    OP
       2017-05-30 10:42:47 +08:00
    @Xs0ul 哈哈,是呀,但是这种概率虽然很小,仍然存在不是嘛。如果实在是没招了,也就只能考虑这种方案了
    geelaw
        15
    geelaw  
       2017-05-30 10:56:17 +08:00
    什么叫“随机”?符合哪种分布?
    slucus
        16
    slucus  
    OP
       2017-05-30 11:00:08 +08:00
    @geelaw 我只是来提问的。。。
    - -!
    geelaw
        17
    geelaw  
       2017-05-30 11:06:26 +08:00
    @slucus 你这个问题问得就没有含义
    slucus
        18
    slucus  
    OP
       2017-05-30 11:08:33 +08:00
    @geelaw 求指教,如何问得有含义,有深意
    geelaw
        19
    geelaw  
       2017-05-30 11:13:51 +08:00   ❤️ 1
    @slucus 你现在问的问题和

    > 如何从一个非空一维数组里面随机拿一个元素出来

    一样。这个问题是没有意义的,有意义的是下面这个问题

    > 如何从一个非空一维数组里面 **均匀** 随机拿一个元素出来

    我可以尝试猜测一下你的问题的含义:

    考虑两个自然数 m、n 满足 mn > 2,考虑

    S = { (a,b,c,d)∈[m]×[n]×[m]×[n]: |a-c|>1 或 |b-d|>1 或 a=c,b=d }

    问如何生成 S 上的均匀分布。

    这个结果和“不断同时取两个位置,如果相邻就丢弃重来”的效果会是一样的。又或者你想要的分布是另外一个分布。

    如果你不说你想要什么样的分布,这个问题就是没有意义的。
    slucus
        20
    slucus  
    OP
       2017-05-30 11:27:50 +08:00
    @geelaw 受教了[抱拳],其实这个问题是要配上数组看的,光靠文字很难简短的描述出来,所以我写出了数组。。。。

    数组取随机数( 2 或 3 个),取到的数据上下左右不相邻?

    从哪里取,恩,一个非空的数组,
    取多少,2 或 3 个,
    取到的数据有什么限制(要求?重点?),上下左右不相邻。

    感觉还行啊。。。
    geelaw
        21
    geelaw  
       2017-05-30 11:44:33 +08:00   ❤️ 2
    @slucus ……………………我说了这么一大段,您简略一下就完全失去含义了。

    如果我总是返回 (0,0), (1,1) 这两个位置你看可以吗?肯定不可以对吧?

    而且这个问题和数组本身没有什么关系,是对位置的随机。

    (刚刚搞错了,没必要假设 m、n 的范围,只要是正整数即可)

    回到题目,假设你要求的是我所说的那种随机,那么一个可行的方案是:先生成第一个位置,然后生成根据第一个位置生成第二个位置。

    例如:用 0 为下标起点。

    第一步,生成一个均匀随机位置 (a,b);
    第二步算出 k = mn,设置 u=v=x=y= +∞;
    第三步:
    - 如果 (a,b) 不是首行,k 减少 1,u=(a-1)*m+b ;
    - 如果 (a,b) 不是首列,k 减少 1,v=a*m+b-1 ;
    - 如果 (a,b) 不是末行,k 减少 1,x=(a+1)*m+b ;
    - 如果 (a,b) 不是末列,k 减少 1,y=a*m+b+1。
    此时 k 代表剩下可以选的位置数目;
    第四步:生成 0 到 k (左含右不含)的一个随机数 t ;
    第五步:
    - 如果 t >= u,t 增加 1 ;
    - 如果 t >= v,t 增加 1 ;
    - 如果 t >= x,t 增加 1 ;
    - 如果 t >= y,t 增加 1 ;
    第六步:设置 (c,d) = (floor(t / m), t mod m);

    输出:(a,b,c,d)。

    对于 3 或者更多个也有类似的方法。

    另一种方法是逐步拒绝。

    第一步:生成一个均匀随机的位置(a,b);
    第二步:反复生成均匀随机的位置(c,d)直到(c,d)和(a,b)不是上下左右相邻;
    输出:(a,b,c,d)。
    imn1
        22
    imn1  
       2017-05-30 12:55:04 +08:00
    如果确定格式是这样——每行只有两个数,这就好办了
    同一列,二进制右边第一位是相同的
    同一行,二进制右边第二位是相同的
    抓住这两点就可以了

    什么?值不一定是连续的?
    我说的是位置,index 总是连续的吧?
    zhuzhuyule
        23
    zhuzhuyule  
       2017-05-30 22:52:15 +08:00
    @blankme 竟然不 @我,差评哟。 确实哟,看了我是老了[哭笑] !
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2492 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 15:38 · PVG 23:38 · LAX 07:38 · JFK 10:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.