5

以下のコードが印刷されることを期待していますchr7

import strutils

var splitLine = "chr7    127471196  127472363  Pos1  0  +".split()
var chrom, startPos, endPos = splitLine[0..2]
echo chrom

代わりに、それは印刷し@[chr7, 127471196, 127472363]ます。

シーケンスから複数の値を同時にアンパックする方法はありますか?

そして、要素が連続していない場合、上記を行う最も簡単な方法は何でしょうか? 例えば:

var chrom, startPos, strand = splitLine[0..1, 5]

エラーが発生します:

read_bed.nim(8, 40) Error: type mismatch: got (seq[string], Slice[system.int], int literal(5))
but expected one of:
system.[](a: array[Idx, T], x: Slice[system.int])
system.[](s: string, x: Slice[system.int])
system.[](a: array[Idx, T], x: Slice[[].Idx])
system.[](s: seq[T], x: Slice[system.int])

  var chrom, startPos, strand = splitLine[0..1, 5]
                                         ^
4

4 に答える 4

5

これは、マクロを使用して実現できます。

import macros

macro `..=`*(lhs: untyped, rhs: tuple|seq|array): auto =
  # Check that the lhs is a tuple of identifiers.
  expectKind(lhs, nnkPar)
  for i in 0..len(lhs)-1:
    expectKind(lhs[i], nnkIdent)
  # Result is a statement list starting with an
  # assignment to a tmp variable of rhs.
  let t = genSym()
  result = newStmtList(quote do:
    let `t` = `rhs`)
  # assign each component to the corresponding
  # variable.
  for i in 0..len(lhs)-1:
    let v = lhs[i]
    # skip assignments to _.
    if $v.toStrLit != "_":
      result.add(quote do:
        `v` = `t`[`i`])

macro headAux(count: int, rhs: seq|array|tuple): auto =
  let t = genSym()
  result = quote do:
    let `t` = `rhs`
    ()
  for i in 0..count.intVal-1:
    result[1].add(quote do:
      `t`[`i`])

template head*(count: static[int], rhs: untyped): auto =
  # We need to redirect this through a template because
  # of a bug in the current Nim compiler when using
  # static[int] with macros.
  headAux(count, rhs)

var x, y: int
(x, y) ..= (1, 2)
echo x, y
(x, _) ..= (3, 4)
echo x, y
(x, y) ..= @[4, 5, 6]
echo x, y
let z = head(2, @[4, 5, 6])
echo z
(x, y) ..= head(2, @[7, 8, 9])
echo x, y

マクロは、..=タプルまたはシーケンスの割り当てをアンパックします。var (x, y) = (1, 2)たとえば、 で同じことを実現できますが..=、seq と配列でも機能し、変数を再利用できます。

headテンプレート/マクロは、タプル、配列、または seq から最初の要素を抽出し、それらcountをタプルとして返します (これは、他のタプルと同様に使用できletますvar

于 2015-08-12T21:29:49.537 に答える
1

さらに別のオプションはpackage definesugarです:

import strutils, definesugar

# need to use splitWhitespace instead of split to prevent empty string elements in sequence
var splitLine = "chr7    127471196  127472363  Pos1  0  +".splitWhitespace()
echo splitLine

block:
  (chrom, startPos, endPos) := splitLine[0..2]
  echo chrom # chr7
  echo startPos # 127471196
  echo endPos # 127472363

block:
  (chrom, startPos, strand) := splitLine[0..1] & splitLine[5] # splitLine[0..1, 5] not supported
  echo chrom
  echo startPos
  echo strand # +

# alternative syntax
block:
  (chrom, startPos, *_, strand) := splitLine
  echo chrom
  echo startPos
  echo strand

最近の議論については、 https://forum.nim-lang.org/t/7072を参照してください

于 2020-11-12T09:06:10.027 に答える