php返回N个不重复的随机数

应用场景:需要从数据库中随机查询多条数据,mysql反对使用order by rand(),因为效率太差。也看到通过子查询来模拟的,不过还是麻烦。最简单的方法,就是读取数据表中的max(id),然后在程序中生成N个随机数,然后应用where id in (?)来获取数据。

php程序生成N个随机数的思想就是定义一个N大小的数组用来存放随机数,每次生成一个随机数都遍历一遍数组,如果已经存在就丢弃,如果不存在就插入到数组中,直到数组的随机数已满。

程序如下:

/**
 * 获取$num个不重复的随机数数组
 *
 * @param $min integer 随机数的最小值
 * @param $max integer 随机数的最大值
 * @param $num integer 随机数的数量
 * @return array $num个随机数
 */
function random_numbers($min, $max, $num) {
    if ($num > $max - $min + 1  $num  1) {
        return null;
    }

    $numbers = array();
    $numbers[] = rand($min, $max);
    $tempnum = 1;

    while ($tempnum  $num) {
        $new_num = rand($min, $max);
        $is_repeat = false;
        foreach ($numbers as $number) {
            if ($number == $new_num) {
                $is_repeat = true;
                break;
            }
        }
        if (!$is_repeat) {
            $tempnum++;
            $numbers[] = $new_num;
        }
    }
    return $numbers;
}

其他语言的实现方式也类似。

Posted in  php


javascript的StringBuffer类

javacript的字符串拼接和java一样是很低效的,不同的是javascript的类库中并没有java中的StringBuffer或StringBuilder。不过我们还是可以通过数组来模拟StringBuffer类:

function StringBuffer() {
    this._objArray = [];
    this._undoFlag = false;
};

StringBuffer.prototype.toString = function() {
    if(this._objArray.length==0) {
        return '';
    }
    var str = this._objArray.join('');
    if(this._objArray.length > 1) {
        this.clear();
        this.append(str);
    }
    this._undoFlag = false;
    return str;
};

StringBuffer.prototype.append = function(object) {
    this._objArray[this._objArray.length] = object;
    this._undoFlag = true;
    return this;
};

StringBuffer.prototype.clear = function() {
    this._objArray.length = 0;
    this._undoFlag = false;
};

StringBuffer.prototype.undoLastAppend = function() {
    if(this._undoFlag) {
        this._objArray.length = this._objArray.length -1;
        this._undoFlag = false;
    }
};

StringBuffer.prototype.setSize = function(size) {
    if(size==null || size=0) {
        this.clear();
        return;
    }
    var str = this._objArray.join('');
    if(size  str.length) {
        str = str.substring(0, size);
        this.clear();
        this.append(str);
    } else if(this._objArray.length > 1) {
        this.clear();
        this.append(str);
    }
    this._undoFlag = false;
};

StringBuffer.prototype.getSize = function() {
    var str = this.toString();
    return str.length;
};

用法也和java中的StringBuffer一样,很不错吧_^

Posted in  javascript


人生第一个10公里

上在世纪公园参加了Nike举办的10公里健身跑,1小时1分钟,创下了个人最好成绩(呵呵,第一次跑),挺有成就感的!

据说全世界有数百万人一起跑这10公里,不过时间倒是改了又改,从下午的6点集合,到4点半集合,再到最后的早上6点半,这个有点不爽。早上5点15就已经起床了,赶早上的二号线去世纪公园,路上看到越来越多的活动参加者穿着统一服装进入车厢,等到了目的地,已是茫茫多的人了。

首先是去领了一个Nike健身背囊,把随身的东西都塞进去了,然后就跟着大部队去起跑区等待。开跑之前被一场突如其来的阵雨浇得浑身湿透,还好背囊是防水的,不过还是把手机关掉了。周围的人大多很兴奋,丝毫没有受到这场雨的影响,还在队伍中看到一些老爷爷老太太呢。

7点30正式开始,慢慢开始走向起跑线,等到踩上起跑线上的计时地毯时,就开始大踏步地向前跑起来了。第一次参加这样的活动,跑起来还是有点紧,可能和平时跑惯了塑胶跑道,跑马路不习惯的关系吧。一路上雨下下停停,感觉还是比较凉爽的。一开始是绕着世纪公园的外面跑一圈,超过不少人,也被不少人超过,马路边上时不时会有饮料区,拿起一杯佳得乐,喝上一两口,然后扔掉。全身完全湿透,混杂着雨水、汗水还有饮料水,呵呵。

前五公里还是比较轻松,跑得比较快的,两个腿稍微有点酸,不过没什么问题,后五公里进入世纪公园内跑一圈,就有点累了,两腿慢慢感觉有点沉,速度也有点下降了。还被忽悠了一下,一个工作人员在我们刚进世纪公园,喊了一句“还有两公里,加油”,一阵兴奋,感觉就快到了,结果跑了没多久发现了跑过7公里的指示牌,那个郁闷啊。

路上还看到不少牛人,7公里的地方,一位高举“饮水思源”大旗的男生从我身边飞似地跑过去了,看到交大的人很亲切,想跟着他跑,不过这仁兄实在太快;8公里处有位老爷爷开始喊“121”的口号,真是佩服佩服。路上一直和几位老爷爷跑在一起,好几次看到他们从我身边超越,却没发现我是什么时候超越他们的,不过他们在终点的时候还是跑在了我的前面。听说头几名的专业选手半个多小时就跑完了呢,厉害啊。

一路上始终没有停下来,一路跑着,虽然有段时间两腿很沉很沉,不过还是坚持下来了,冲过终点线的时候,看着计时牌显示1小时5分钟,很兴奋,比想象中跑得要快,虽然也比想象中要累一点。走了一段路之后,去领取了一件完赛的Nike T-shirt,嘴里咸咸的,赶紧拿起一瓶佳得乐狂喝。

跑完在雨中漫步,感觉很舒畅,很爽。

Posted in  life


用css截取字符串

一般网页上显示字符串有两种方式,一是通过程序语言,如php, java来截取,二是通过css来截取。前者的缺点是页面上字符缺失,不利于SEO,而且遇到中英文混合时,往往造成截取长度不同;css的缺点是有可能在页面上看到截取一半的字。不过总体还是css的优点占优。

下面是css截取字符串的代码:

div {
  width:300px;
  white-space:nowrap;
  overflow:hidden;
  float:left;
  -o-text-overflow:clip;     /* for Opera */
  text-overflow:clip;        /* for IE */
}

如果你想在截取字符串之后加上...可以用以下的代码:

div {
  width:300px;
  white-space:nowrap;
  overflow:hidden;
  float:left;
  -o-text-overflow:ellipsis;     /* for Opera */
  text-overflow:ellipsis;        /* for IE */
}
div:after {
  content:"...";   /* for Firefox */
}

Posted in  css


sql杂谈

在学校里学SQL,也实际操作过,觉得还是掌握的不错的。这两天在公司一用,缺点就暴露了。

以前做的应用,数据量有个几千上万就不错了,写的SQL语句也大多比较简单,跑跑都不成问题。这两天公司有张数据表A的数据量已经达到24万,我要做的是将这张表A的数据LEFT JOIN另外一张表B,在mysql客户端上一跑,没有反应,等了好几分钟都出不来结果,只能Ctrl+C。看了好久都看不出SQL语句错在哪里,自己另外建了两个表作实验,也没有问题,很快就能显示结果。后来在同事的提醒下,原来是B表关联的字段没有加index,加上index之后果然很快就显示结果了。

平时自己在实验SQL语句的时候大多将精力集中在SQL语句是否正确,而忽略了SQL语句的性能,好比今天用子查询来找数据,结果发现还不如分成两条SQL语句来的效率高呢。书本上将的金玉良言大多是很有用的,但是也有部分在实际应用中是必须违反的,比如几大范式要避免冗余,但是实际应用中还是会通过增加冗余来提高查询效率。

看来应该好好在研究一下数据库的性能问题了呢。

Posted in  sql


Fork me on GitHub