2013-07-02 3 views
0

안녕 모두 내가 tcl 배열에 대한 도움이 필요해.tcl에 기존 배열을 만들고 추가하기

proc A {} { 
     set lst_A [list]; 
     if {true} { 
     lappend lst_A [::B $file1]; 
     } else { 
     foreach id $allId { 
      lappend lst_A [::B $id]; 
     } 
     } 
     return $lst_A; 
    } 

    proc B {fileID} { 
     set fileName [::getFileName $fileID]; # getFileName returns filename from fileid 
     set tcName "[set ItemName]_[set ItemId]"; 
     array set tcArrayName {$fileName $tcSpec}; 
     return $tcArrayName; 
    } 

지금 내가 키가 해당 ID와 관련된 몇 가지 이름의 파일 ID와 값의 일종 인 키 - 값 쌍 될 것입니다 배열을 만들려면 : 나는 다음과 같은 TCL 뭔가에 두 가지 절차가 있습니다. 이제 상황이 proc에있는 경우 조건이 true 인 경우 하나의 키 - 값 쌍만을 사용하여 배열을 만들고이 배열을 lst_A에 추가합니다.이 경우이 경우 하나의 항목 즉 배열이 반환됩니다. 하지만 조건이 내가 일부 ID를 통해 반복하고 각 ID에 대해 proc B를 호출하고이 경우 여러 개의 키 - 값 쌍 배열을 포함 할 lst_A에 추가되는 배열을 만드는 것보다 거짓이면.

그래서 위의 두 절차를 작성하고 tcl 자습서에서 배열에 대해 읽은 후에 배열을 만들었습니다. 그러나 이것이 올바른 방법인지 또는 가장 최적화 된 방법인지 확실하지 않습니다.

궁극적 인 목표는 lst_A를 만들거나 조건이 참일 경우 하나의 키 - 값 쌍을 포함하거나 둘 이상의 키 - 값 쌍이있는 배열이되어야한다고 말합니다. 나는 proc B에서 배열을 생성하기 때문에 배열로 proc B의 키 - 값 쌍을 반환 한 다음 해당 배열을 proc A의 lst_A에 추가 할 수 있습니다.

제안 사항 ???

답변

5

배열의 목록을 여기에 혼동스럽게합니다.

tcl에서는 배열을 함수로 전달하거나 함수에서 반환 할 수 없습니다. 또한 tcl은 C++이 "맵"이라고 부르는 Perl과 Ruby의 "해시"또는 Javascript가 "객체"라고 부르는 것에 대해 "배열"이라는 용어를 사용합니다. 이 모든 것은 일반적으로 컴퓨터 과학에서 "연관 배열 (associative arrays)"로 알려져있다. 따라서 tcl의 "배열"은 데이터의 순서가 아니라 키 - 값 쌍입니다.

배열은 일반적으로 값으로 변하지 않습니다 (또는 숙련 된 tcl 프로그래머가 "문자열"이라고 부르는 것). 따라서이 :

array set tcArrayName {$fileName $tcSpec}; 
return $tcArrayName; 

구문 오류가 발생

can't read "tcArrayName": variable is array 

당신은 실제로 당신이 다음 반환 할 수있는 값으로 배열의 내용을 변질 수 있습니다.

"$fileName $tcSpec" 

도에 발생 : 위의 명령은 두 가지 요소 목록의 형태로 tcArrayName 배열의 내용을 반환합니다

return [array get tcArrayName] 

:하지만 당신은 [array get] 명령을 통해 수동으로해야 끈이어야한다. '$'다음에 'f', 'i', 'l', 'e', ​​'N', 'a', 'm', 'e'등의 실제 문자열이 있습니다. 파일 이름 및 연결된 항목 이름 및 항목 ID 리터럴 문자열 "$ fileName $ tcSpec". 당신이 코드 줄에 {} 그룹을 사용했기 때문이다

: TCL에서

array set tcArrayName {$fileName $tcSpec} 

, {xxx}'xxx' 펄에서와 같은 방식으로 동작합니다. 기본적으로 대체되지 않는 리터럴 문자열입니다.당신은 TCL이 $ 대체를하고 싶은 경우에 당신은 "" 그룹 사용해야 :

array set tcArrayName "$fileName $tcSpec" 

을하지만 fileName 공백이 포함 된 경우 다음 코드를 깰 때문에이 허약하다.

array set tcArrayName [list $fileName $tcSpec] 

그러나 당신이하고있는 모든 또한 더에 dict로 알려진 키 - 값 목록 (그것을 초기화하기 때문에이 경우에 array를 사용하여 약간의 중복 :이 작업을 수행하는보다 강력한 방법입니다 tcl의 최신 버전, tcl의 어떤 버전을 사용하고 있습니까?) 즉시 폐기하고 키 - 값 목록으로 컨텐츠를 반환하십시오.

proc B {fileID} { 
    set fileName [::getFileName $fileID]; # getFileName returns filename from fileid 
    set tcName "[set ItemName]_[set ItemId]" 
    return [list $fileName $tcSpec] 
} 

그러나 우리는 분명히 아직하지 않은 : 단순히 키와 값의 목록을 반환하지 왜

.

can't read "ItemName": no such variable 

TCL은 기본적으로 함수로 전역 변수를 가져 오지 않기 때문이다 : 당신이 B를 실행하려고하면이 오류가 표시됩니다. 따라서 ItemNameItemId 변수는 B에 없습니다.

proc B {fileID} { 
    global ItemName 
    global ItemId 

    # ... 
} 

또는 전역 네임 스페이스를 통해 액세스를 정규화 된 변수 이름 사용 :

set tcName "[set ::ItemName]_[set ::ItemId]" 

그래서 B은 다음과 같아야합니다

을 당신은 global 명령을 통해 명시 적으로 가져올 필요 하나
proc B {fileID} { 
    set fileName [::getFileName $fileID]; # getFileName returns filename from fileid 
    set tcName "[set ::ItemName]_[set ::ItemId]" 
    return [list $fileName $tcSpec] 
} 

그건 B입니다. 그러나 A도 처리해야합니다 :

예상대로

proc A {} { 
    set lst_A [list]; 
    if {true} { ;# assuming that there will be a valid condition here 
    lappend lst_A [::B $::file1]; 
    } else { 
    foreach id $allId { 
     lappend lst_A [::B $id]; 
    } 
    } 
    return $lst_A; 
} 

이 작동합니다 :

can't read "file1": no such variable 

우리는 변수 file1에 액세스 할을 약간 수정해야합니다.

키 - 값 목록을 사용할 때 약간의 속도를 높이려면 dicts을 읽어야합니다. 즉, dicts는 위에 주어진 코드에 영향을 미치지 않지만 코드 A에 영향을줍니다. dicts를 사용하려는 경우 위 전화를 dict append으로 바꿀 수 있습니다. 그러나 이전 버전의 tcl에는 dict이 없습니다.

+0

8.6을 사용하는 경우 다음과 같이 작성할 수 있습니다. if {1} {return [list [B $ :: file1]] else {return [lmap id $ : allId {B $ id }]}}' –

+0

그래도 8.6 대신 lect 대신'dict append'를 사용하여 foreach를 사용하면 dict-list shimmering을 피할 수 있기 때문에 더 좋습니다. – slebetman

+0

위의 문제를 해결해 주셔서 감사합니다. 내 실제 문제를 해결하는 다른 방법을 찾았지만 귀하의 대답은 배열 사용에 대한 훌륭한 설명이었습니다. Slebetman에게 다시 한번 감사드립니다. :) –