用于虚拟“表”的多列插入算法?

时间:2013-05-01 21:17:36

标签: javascript sorting

我有一个由“数组”构成的JavaScript“表”,其中“行”表示对象共享相似的结构(成员属性类似于“列”形式,其值为“单元格”)。

该表已按照级联方式使用一个或多个列进行排序,其中mergesort以相反的顺序应用,并且可以是20到20,000行的任何位置。

用于在正确的位置将新行插入表中的最佳算法是什么,而无需对整个表进行重新排序(或者更确切地说,以查找新行的插入索引 )?

这方面的一个例子是:

Sort Order = name, id

id    name    description
0     a       blah
1     b       foo
2     d       blah
3     d       blah 2
...
19    d       blah 18

Insert:

id    name    description
20    c       bar

To Yield:

id    name    description
0     a       blah
1     b       foo
20    c       bar
2     d       blah
3     d       blah 2
...
19    d       blah 18

(对所有引用的定义感到抱歉,当我第一次尝试提出这个问题时,人们认为“表格”被称为SQL数据库表或类似表格时会出现很多混淆)

1 个答案:

答案 0 :(得分:0)

对于任何感兴趣的人解决此问题如下:

var table = [
    {i: 0, id: 0, id2: 0, id3: 0},
    {i: 1, id: 0, id2: 1, id3: 0},
    {i: 2, id: 1, id2: 0, id3: 0},
    {i: 3, id: 1, id2: 2, id3: 0},
    {i: 4, id: 1, id2: 3, id3: 0},
    {i: 5, id: 2, id2: 0, id3: 1},
    {i: 6, id: 2, id2: 0, id3: 2},
    {i: 7, id: 2, id2: 1, id3: 0},
    {i: 8, id: 2, id2: 1, id3: 1},
    {i: 9, id: 2, id2: 2, id3: 0}
    ];

var sort = ['id', 'id2'];

function InsertionIndex(table, sort, row) {
    var state = {
        _compare: function (left, right) {
            if (left < right) { return (1); }
            else if (left > right) { return (-1); }
            return (0);
        },
        column: '',
        max: table.length,
        min: 0,
        row: row,
        _search: function (state) {
            var minc = this._compare(this.table[this.min][this.column], state.row[this.column]);
            var maxc = this._compare(this.table[this.max - 1][this.column], this.row[this.column]);
            if (state.table[state.min][state.column] == state.table[state.max - 1][state.column]) { return; }
            if (minc < 0) { state.max = state.min; return; }
            if (maxc > 0) { state.min = state.max; return; }
            if ((state.max - state.min) > 2) {
                var mid = Math.ceil((state.min + state.max) / 2);
                var midc = state._compare(state.table[mid][state.column], state.row[state.column]);
                if (midc < 0) {
                    state.max = mid;
                    state._search(state);
                    return;
                } else if (midc > 0) {
                    state.min = mid;
                    state._search(state);
                    return;
                } else {
                    for (var i = mid - 1; i >= state.min; i--) { if (state._compare(state.table[i][state.column], state.row[state.column]) != 0) { state.min = i + 1; break; } }
                    for (var i = mid + 1; i < state.max; i++) { if (state._compare(state.table[i][state.column], state.row[state.column]) != 0) { state.max = i; break; } }
                    return;
                }
            } else {
                if (maxc < 0) {
                    if (minc > 0) { state.min = state.max - 1; state.max = state.max - 1; return; }
                    else { state.max = state.max - 1; return; }
                } else if (minc > 0) {
                    state.min = state.max - 1; return;
                }
            }
            return;
        },
        table: table
    };
    for (var i = 0; i < sort.length; i++) {
        state.column = sort[i];
        state._search(state);
        if (state.min >= state.max) { break; }
    }
    return ({ max: state.max, min: state.min });
}

for (var i = 0; i < table.length; i++) {
    document.write(table[i].i + '&nbsp;&nbsp;&nbsp;&nbsp;' + table[i].id+ '&nbsp;&nbsp;&nbsp;&nbsp;' + table[i].id2 + '&nbsp;&nbsp;&nbsp;&nbsp;' + table[i].id3 + '<BR />');
}
var insertion = {i: 3, id: 0, id2: 1, id3: 1};
document.write(InsertionIndex(table, sort, insertion).min + '&nbsp;&nbsp;&nbsp;&nbsp;' + InsertionIndex(table, sort, insertion).max + '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;2<BR />');
insertion = {i: 3, id: 1, id2: 1, id3: 1};
document.write(InsertionIndex(table, sort, insertion).min + '&nbsp;&nbsp;&nbsp;&nbsp;' + InsertionIndex(table, sort, insertion).max + '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;3<BR />');
insertion = {i: 3, id: 2, id2: 1, id3: 1};
document.write(InsertionIndex(table, sort, insertion).min + '&nbsp;&nbsp;&nbsp;&nbsp;' + InsertionIndex(table, sort, insertion).max + '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;9<BR />');
insertion = {i: 3, id: 3, id2: 1, id3: 1};
document.write(InsertionIndex(table, sort, insertion).min + '&nbsp;&nbsp;&nbsp;&nbsp;' + InsertionIndex(table, sort, insertion).max + '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp;10<BR />');