【问题标题】:Random sampling of non-overlapping substrings of length k长度为 k 的非重叠子串的随机采样
【发布时间】:2013-05-15 09:21:52
【问题描述】:

给定一个长度为 n 的字符串,我将如何(伪)随机采样 m 个大小为 k 的子字符串,使得没有采样子串重叠?我的大部分脚本编写经验都是用 Perl 编写的,但任何通用语言的易于运行的解决方案就足够了。

【问题讨论】:

  • 将字符串分成所需长度的样本;可能通过填充数组,然后my $rnd = $array[int rand @array]
  • 我想我会考虑到有n-m*k 字符不会 被使用,以及m+1 可以进入的空白。选择那些m+1 间隙的长度,这样它们加起来正好是n-m*k。 (这样就不需要考虑重叠了。)
  • 我假设子字符串需要是连续的(否则使用迭代器很容易做到)?
  • @ali_m 是的,子字符串是指原始字符串中的 k 个连续字符的字符串。
  • 你为什么要这样做?我不确定我能想到一种算法,它不会偏向选择非常接近字符串开头或结尾的字符,所以它不会是“公平的”

标签: python string perl random sample


【解决方案1】:

如果输入中存在不能出现的字符,例如X,只是:

my $size = 20;
my $count = 20;
my $mark = 'X';
my $input = 'CCACGCATTTTTGTTCATTGTTCTGGCTTCTTACAAGGTTCAGTAGACTTTGTAACACAGTTGTGTCTCTCACAGATTGGCAGATGTTTGGTAAAGGATTGACTTTTCAGCCAACTCATGGGAAAGTGAAATAATGTAAAAAACAGGAAGAATACAGTTTTAGGCCTTTCAAGTGAGGCATGGCTTTCAGCTCTTGGCAAGAACAGGCAAGGAGATGCAAGTTTTAGGACTCTAAGAGGCTAGGCTTTTCAAAGTGCTTCTCTCCCCTTCACCCTCCTTCAGTTACAGCACCAAGCACCACCGAGGTGTTACCTGCAGCCTCACTCTCTACCTGGTTGTGGGATCCTGCCACTTCCTTAACCCACACTGAGTTCCTTGTGGTTCACAGGGTCACACAGAGGGCTGTAGAGATACAAAAGATATATGTGATTTTATATCACCTATCATATGAAGATATATTTATAAAATAGGAAACATATTAACCACTTATCATTTTATATATTTATGGTTTTATGTGTCAAAAATATATTGTTTCATGTATGTATTAAAGGATAAGTATGTATAAGAGGTTTTATAGATGTGTAAAATTATATATTTATACGTATCTTTACAAATTTAAGAATAAAGGAAGGAAAATTCTCAAAGAGGAATTCAGATATCAAGCAGTGCCCTTTGACCAAGAGCCTTGGTTACAACATACCTACAAAAGTGAACTATCATTGAAAGACCTATGGACACTGGATTTCTCTTTCCTTATTTAGAAGGGCAGTCTGTGTCTTGGAAAAGCATACAGTTTGTTGTATCTTGCTGGACAACAGGAGTCA';

if (2*$size*$count-$size-$count >= length($input)) {
    die "selection may not complete; choose a shorter length or fewer substrings, or provide a longer input string\n";
}

my @substrings;
while (@substrings < $count) {
    my $pos = int rand(length($input)-$size+1);
    push @substrings, substr($input, $pos, $size, $mark x $size)
        if substr($input, $pos, $size) !~ /\Q$mark/;
}

【讨论】:

  • 非常清晰和简单的答案。不过有一个问题,正则表达式中\Q 的用途是什么?
  • 看起来它的分布也相当公正:i.imgur.com/EPLexRr.png
  • 如果您将 $mark 设置为类似“|”的内容。是的,这应该是公正的(但如果您要占用超过一半的字符串,甚至拒绝尝试)
  • 啊,I see。谢谢!
【解决方案2】:

这是 Python 中的递归方法。在每个步骤中,从字符串的剩余分区中随机选择,然后从所选分区中随机选择长度为 k 的子字符串。将此分区替换为所选子字符串上的分区拆分。过滤掉长度小于 k 的分区,然后重复。当有 m 个子字符串,或者没有剩余长度大于或等于 k ​​的分区时,返回子字符串列表。

import random

def f(l, k, m, result=[]):
    if len(result) == m or len(l) == 0:
        return result
    else:
        if isinstance(l, str):
            l = [l]
        part_num = random.randint(0, len(l)-1)
        partition = l[part_num]
        start = random.randint(0, len(partition)-k)
        result.append(partition[start:start+k])
        l.remove(partition)
        l.extend([partition[:start], partition[start+k:]])
        return f([part for part in l if len(part) >= k], k, m, result)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多