2016-11-11 44 views
1

我有一个列表包含映射如下TCL计算映射

# {from, to, count} 
{{XD} PD 2} 
{{XB} PB 4} 
{{XA0, XA1} PA 4} 

如何创建使用TCL

从[XD,XB,XA0,XA1]和[PD,PB,PA]映射
Expected 

# XD XB XA0 XA1 
{{PD0 PB0 PA0 PA1} 
{ PD0 PB0 PA2 PA3} 

{ PD0 PB1 PA0 PA1} 
{ PD0 PB1 PA2 PA3} 

{ PD0 PB2 PA0 PA1} 
{ PD0 PB2 PA2 PA3} 

{ PD0 PB3 PA0 PA1} 
{ PD0 PB3 PA2 PA3} 


{ PD1 PB0 PA0 PA1} 
{ PD1 PB0 PA2 PA3} 
....} 
+1

你有什么尝试?将XA1设置为单独的映射条目将使您的生活更轻松。 –

+0

这是一个非平凡的转换,正是因为来自单个序列计数器的值在多列中使用的方式。 –

回答

1

这个问题最好是递归处理。特别是,为特定计数器生成计数会导致回调以处理链中的下一个计数器。需要注意的是按照正确的顺序将结果拼凑在一起(有几种方法可以实现),但下面的方法很好,因为它将数据生成为列表列表,从而可以对其进行进一步处理,根据您的选择打印。

请注意使用默认参数关闭递归。通过使用包装程序可以避免这种情况,但这是一种改进。

proc genseq {definition {current {}}} { 
    # Get the next part of the definition 
    lassign [lindex $definition 0] columns prefix limit 
    set definition [lrange $definition 1 end] 

    set result {} 
    for {set i 0} {$i < $limit} {} { 
     # Handle the appending of bits relating to the counter at the current level 
     set cur $current 
     foreach c $columns { 
      lappend cur "$prefix$i" 
      incr i 
     } 

     # If we have more definition to process, recursive call. Otherwise just accumulate 
     if {[llength $definition] > 0} { 
      lappend result {*}[genseq $definition $cur] 
     } else { 
      lappend result $cur 
     } 
    } 
    return $result 
} 

让我们来测试一下:

set seqinfo { 
    {{XD} PD 2} 
    {{XB} PB 4} 
    {{XA0 XA1} PA 4} 
} 

# A bit of trickery to get approximately the right output format 
puts \{\{[join [genseq $seqinfo] "\}\n\{"]\}\} 

,输出结果。

 
{{PD0 PB0 PA0 PA1} 
{PD0 PB0 PA2 PA3} 
{PD0 PB1 PA0 PA1} 
{PD0 PB1 PA2 PA3} 
{PD0 PB2 PA0 PA1} 
{PD0 PB2 PA2 PA3} 
{PD0 PB3 PA0 PA1} 
{PD0 PB3 PA2 PA3} 
{PD1 PB0 PA0 PA1} 
{PD1 PB0 PA2 PA3} 
{PD1 PB1 PA0 PA1} 
{PD1 PB1 PA2 PA3} 
{PD1 PB2 PA0 PA1} 
{PD1 PB2 PA2 PA3} 
{PD1 PB3 PA0 PA1} 
{PD1 PB3 PA2 PA3}} 

我会放在标题和额外的空间行作为练习。 (另外,Tcl没有用逗号分隔列表;实际上,逗号是普通字符,在表达式之外对它们没有什么特别之处。)

+0

嗯...我可能只是有一个循环和每个序列项目的计数器。不够优雅,停止条件会混乱。 –

1

那么我看着期望的输出,并认为它看起来像怀疑的笛卡儿乘积一组关系值。所以,在用大锤灭蝇的精神,你可以用关系使用TclRAL(http://chiselapp.com/user/mangoa01/repository/tclral/index),关系代数扩展TCL,并做到这一点:

package require ral 

# The original format of the spec. 
set mapspec { 
    {XD PD 2} 
    {XB PB 4} 
    {{XA0 XA1} PA 4} 
    } 
# Way too much code required to convert from 
# the original data to a set of relation values. 
foreach spec $mapspec { 
    lassign $spec attrs body count 
    set heading [list] 
    foreach attr $attrs { 
     lappend heading $attr string 
    } 
    set tuples [list] 
    for {set i 0} {$i < $count} {} { 
     set tuple [list] 
     foreach attr $attrs { 
      lappend tuple $attr $body$i 
      incr i ; # assume count % [llength $attrs] == 0 
      # puts "tuple = $tuple" 
     } 
     lappend tuples $tuple 
     # puts "tuples = $tuples" 
    } 
    set rel [ral relation create $heading {*}$tuples] 
    # puts [ral relformat $rel rel] 
    lappend rels $rel 
} 

# The "real work" is a one liner. 
set prod [ral relation times {*}$rels] 
# Print the result as a table. 
puts [ral relformat $prod "Mapping as a relation value"] 

运行这给:

+------+------+------+------+ 
|XD |XB |XA0 |XA1 | 
|string|string|string|string| 
+------+------+------+------+ 
|PD0 |PB0 |PA0 |PA1 | 
|PD0 |PB0 |PA2 |PA3 | 
|PD0 |PB1 |PA0 |PA1 | 
|PD0 |PB1 |PA2 |PA3 | 
|PD0 |PB2 |PA0 |PA1 | 
|PD0 |PB2 |PA2 |PA3 | 
|PD0 |PB3 |PA0 |PA1 | 
|PD0 |PB3 |PA2 |PA3 | 
|PD1 |PB0 |PA0 |PA1 | 
|PD1 |PB0 |PA2 |PA3 | 
|PD1 |PB1 |PA0 |PA1 | 
|PD1 |PB1 |PA2 |PA3 | 
|PD1 |PB2 |PA0 |PA1 | 
|PD1 |PB2 |PA2 |PA3 | 
|PD1 |PB3 |PA0 |PA1 | 
|PD1 |PB3 |PA2 |PA3 | 
+------+------+------+------+ 
Mapping as a relation value 
--------------------------- 

所有这些都是不值得的,并打算用一种俏皮的精神。除非,那就是,你需要进一步操纵结果。然后关系运算符可以做一些有趣的转换。