2016-11-11 78 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 
--------------------------- 

所有這些都是不值得的,並打算用一種俏皮的精神。除非,那就是,你需要進一步操縱結果。然後關係運算符可以做一些有趣的轉換。