Python 长度为k的非重叠子串的随机抽样

Python 长度为k的非重叠子串的随机抽样,python,string,perl,random,sample,Python,String,Perl,Random,Sample,给定一个长度为n的字符串,我如何(伪)随机地对大小为k的m个子字符串进行采样,从而使所有采样的子字符串都不重叠?我的大部分脚本编写经验都是用Perl编写的,但是用任何通用语言编写一个易于运行的解决方案就足够了。这是Python中的一种递归方法。在每个步骤中,从字符串的剩余分区中随机选择,然后从所选分区中随机选择长度为k的子字符串。将此分区替换为所选子字符串上的分区拆分。过滤掉长度小于k的分区,然后重复。当有m个子字符串,或者没有剩余长度大于或等于k的分区时,子字符串列表将返回 import ra

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

这是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)

如果输入中存在无法出现的字符,例如
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/;
}
my$size=20;
我的$count=20;
我的$mark='X';
我的$input=‘CCACGCATTTTTTTCTCTCTCTCTCATCTCTCTCTCTCAGGTTCAGCATTTCTCAGCATGTCTCAGCATGGTTCAGCATGGTTCAGCATGGGAAGTGATATGTCAAACAGCATAGAGGAAGAGATAGATAGATGTCAGCATTTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTGAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCAGTCACCATTCTTACATACATACATACATACATACATACATAGATATGTGATTACATATATATATATATATACATATTATATATATATATACTACATATATTATATATACTACATATATATATTATCATTCATATGTATATATATATATAGATATATAGATATATATATATATATATATATACATATATATCAATATATTAGAATATTATATATATATATATATACTCAATATATATATATATATATATATATATATATATATATATATATAGAGATATAGATATATATATATAGATAGATATTATATATATACTCAATAGAGATAGATAGATAGATAGATAGATAGATAGAGATAGATCAATAGATCAATCAATATATATATATATTACTACAAAGTGGAATCTCATTGAAGACTCATGGACATTCTCTTTCTTTTAGTCTTAGTCTGTCTTGGAAGCATACAGTTTGTTGTATCTGGACAGAGTCA';
如果(2*$size*$count-$size-$count>=长度($input)){
die“选择可能未完成;请选择较短的长度或较少的子字符串,或提供较长的输入字符串\n”;
}
我的@substring;
while(@子字符串<$count){
my$pos=int rand(长度($input)-$size+1);
推送@substring,substr($input,$pos,$size,$mark x$size)
如果substr($input,$pos,$size)!~/\Q$mark/;
}

将字符串划分为所需长度的样本;可能通过填充数组,然后
my$rnd=$array[int rand@array]
我想我应该考虑到有
n-m*k
字符不会被使用,以及
m+1
它们可以进入的间隙。选择那些
m+1
间隙的长度,使它们加起来正好是
n-m*k
。(这样,你就不需要考虑重叠了。)我假设子串需要是连续的(否则它会很容易用迭代器来处理)?@是的,是的,通过子串,我指的是从原始字符串中的k个连续字符串。为什么要这样做?我不确定我能想出一种算法,它不会偏向于选择字符串开头或结尾附近的字符,因此它不会是“公平的”非常清晰和简单的答案。但是有一个问题,正则表达式中的
\Q
的用途是什么?看起来它也有一个相当无偏的分布:。如果您将$mark设置为类似于“|”的值。是的,这应该是无偏见的(但如果你打算拿走超过一半的绳子,你甚至拒绝尝试)啊。谢谢