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

これはすべて価値のあるものではなく、遊び心があります。ただし、結果をさらに操作する必要がある場合を除きます。そして、関係演算子は興味深い変換を行うことができます。

関連する問題