Tcl中的动态列表排序

时间:2013-11-15 07:46:12

标签: sorting tcl

我想根据动态列表进行一些排序。让我解释一下 我使用的是tcl版本8.4,我无法更改,必须使用

 list1 = {{a b c} {c b c a} {b b a}}    ..... 1st input data

列表1是一个tcl列表,其中有3个成员,它们以任何顺序形成不同类型的子列表,甚至每次都会更改。例如,下次列表1将是:

 list1 = {{c} {b c a} {b c} {a c a c}}    ..... 2nd input data (for next time consideration)

现在我想以这样的方式对它们进行排序:如果我使用它们周围的循环或lsortstring compare或任何其他tcl命令,新的tcl列表应包含基于a的单个成员优先。就像我们有上升/下降一样。 请注意,两种情况下,单个子列表长度都在增加和减少,同时从a,b,c也继续旋转。

在我的情况下,我希望“a”具有最高优先级,然后是“b”,然后是“c”(a-> b-> c)

因此,在第一次迭代完成处理后的输出应为:

$> puts $new_list1
$> {a a a}           # as out of 3 sublists a is present in them and it gets highest priority.

类似地,在第二次迭代完成处理后的输出应为:

$> puts $new_list1
$> {c a b a}    # as you can see that list1 1st element is c so it gets output as is, second sublist has b c and a so `a` gets outputted, 3rd sublist is b and c so `b` gets outputted

让我知道你的想法。

提前致谢!

1 个答案:

答案 0 :(得分:0)

首先,我将研究构建这种数据结构,以便您不必对所有子列表进行排序 - 例如,使用像二进制搜索一样简单的算法linsert每个元素到每个子列表的排序索引。

其次,我会考虑你是否需要像你想象的那样多的“优化”。通常,最好的解决方案(由于可维护性)是最明显的事情:对子列表进行排序,然后使用循环,如下所示:

# construct a new list of sorted sublists
foreach sublist $list {
    lappend presorted_list [lsort $sublist]
}

# given a reference to a list of sorted lists, simultaneously build (1) a list of
# each sublist's first element and (2) a list of the each sublist's remaining
# elements, so that the former can be returned, and the latter can be set by
# reference for the next iteration (and will have omitted any empty sublists)
proc process_once {presorted_list_ref} {
    upvar $presorted_list_ref presorted_list
    foreach sublist $presorted_list {
        if {[llength $sublist] > 0} {
            lappend returning_list [lindex $sublist 0]
            lappend remaining_list [lrange $sublist 1 end]
        }
    }
    set presorted_list $remaining_list
    return $returning_list
}

set iter_1 [process_once presorted_list]
set iter_2 [process_once presorted_list]

如果您不能以开始排序的子列表的方式预处理或构建原始列表,我认为没有更好的方法可以做到这一点。除非从排序的子列表开始,否则您无法决定每个子列表中的哪个项目必须输出,而不检查所有项目 - 所以您也可以排序一次,这样您就会知道始终采用第一个每个子列表的项目,正如我上面编码的那样。


以循环形式,如果您不需要一次特定地检索一次迭代,

foreach sublist $list {
    lappend presorted_list [lsort $sublist]
}

while {[llength $presorted_list] > 0} {

    foreach sublist $presorted_list {
        if {[llength $sublist] > 0} {
            lappend returning_list [lindex $sublist 0]
            lappend remaining_list [lrange $sublist 1 end]
        }
    }

    # 
    #   do stuff with $returning_list
    #

    set presorted_list $remaining_list
}