【问题标题】:TCL code to loop through a string and print only value greater thanTCL 代码循环遍历字符串并仅打印大于的值
【发布时间】:2022-12-16 23:01:37
【问题描述】:

一个文件由多个输入字符串组成,这些字符串由一个固定字母“a”后跟 [0-15]、空格,然后是一个十进制值组成。这些集合中的每一个都包含在花括号中,并由下一个集合用空格分隔。我正在寻找十进制值超过 5.0000 但丢弃最高值 113.1600(第一行)和 208.1150(第二行)的集合。例如。第一个字符串的输出将是 {a7 32.7832} 并且第二个字符串没有输出。

输入:

{a7 32.7832} {a8 1.6795} {a9 0.4920} {a10 0.6235} {a11 0.4190} {a14 3.2500} {a6 1.5170} {a12 0.2620} {a13 0.0410} {a3 2.6730} {a4 2.7620} {a5 0.7490} {a2 2.0300} {a15 113.1600}
{a3 1.0995} {a5 0.3180} {a6 0.3395} {a7 0.5600} {a8 1.4035} {a9 1.1810} {a10 0.4340} {a11 0.3430} {a13 0.6970} {a14 208.1150} {a2 1.4630} {a4 1.0820}
{a3 1.0995} {a5 0.3180} {a6 0.3395} {a7 0.5600} {a8 6.0835} {a9 1.1810} {a10 0.4340} {a11 0.3430} {a13 0.6970} {a14 208.1150} {a2 1.4630} {a4 1.0820}

输出:

{a7 32.7832}
{a8 6.0835}

【问题讨论】:

  • 冒着显而易见的风险,Tcl 和 Perl 是不同的语言。它不像 C 和 C++,它们至少在表面上是相似的。 Tcl 和 Perl 是非常不同的语言。
  • 是的,更正了它。感谢您指出。我一直在寻找解决方案或解决方案 - 以更容易实施的为准。

标签: string loops match tcl


【解决方案1】:

在 TCL 中这很容易做到,因为括号中的字符串被视为列表。然后你只需遍历所有值,跳过任何小于 5 的值,并构建一个不是最高值的列表。

set values {{a7 32.7832} {a8 1.6795} {a9 0.4920} {a10 0.6235} {a11 0.4190} {a14 3.2500} {a6 1.5170} {a12 0.2620} {a13 0.0410} {a3 2.6730} {a4 2.7620} {a5 0.7490} {a2 2.0300} {a15 113.1600}}

set values2 {{a3 1.0995} {a5 0.3180} {a6 0.3395} {a7 0.5600} {a8 1.4035} {a9 1.1810} {a10 0.4340} {a11 0.3430} {a13 0.6970} {a14 208.1150} {a2 1.4630} {a4 1.0820}}

set values3 {{a3 1.0995} {a5 0.3180} {a6 0.3395} {a7 0.5600} {a8 6.0835} {a9 1.1810} {a10 0.4340} {a11 0.3430} {a13 0.6970} {a14 208.1150} {a2 1.4630} {a4 1.0820}}


proc calcValues {values} {
    set outputs [list]
    set max {}

    foreach value $values {
        set num [lindex $value 1]

        if {$num < 5.0} {
            continue
        }

        if {$max eq {}} {
            set max $value
            continue
        }

        if {[lindex $max 1] < $num} {
            lappend outputs $max
            set max $value
        } else {
            lappend outputs $value
        }
    }

    return $outputs
}

puts [calcValues $values]
puts [calcValues $values2]
puts [calcValues $values3]

【讨论】:

  • 列表的第一个元素不必是最大值。编辑问题以显示更多示例。可能存在没有大于 5.0 的情况(除了我们忽略的最大数值)
  • @user8217644 你是对的,我完全忘了考虑初始值小于 5 的问题。我已经修复了
  • 谢谢塞缪尔!如果我有一个包含此类字符串的长文件或分配给变量的字符串集合,这是否会节省时间?
  • TCL 对列表非常有效,所以这应该运行得很好。可能有优化它的方法,但这需要分析和比我更多的 TCL 知识。
【解决方案2】:

这些行绝对是 Tcl 列表;格式受到足够的限制,我们可以说那一定是真的。这很容易;不需要重要的数据调节步骤!您可以使用 lsort -real -index 1 按浮点值对列表对进行排序;排序列表中的第二个元素将是您正在寻找的元素......只要它高于阈值。

foreach line [split $inputData "
"] {
    # Get the pair with the second-highest value in the list
    set target [lindex [lsort -real -index 1 $line] 1]
    # Test against the threshold
    if {[lindex $target 1] >= 5.0} {
        puts $target
        # Could also lappend the target to a result list here
        # You didn't say how you wanted the results
    }
}

【讨论】:

    【解决方案3】:
    set lines {
        {{a7 32.7832} {a8 1.6795} {a9 0.4920} {a10 0.6235} {a11 0.4190} {a14 3.2500} {a6 1.5170} {a12 0.2620} {a13 0.0410} {a3 2.6730} {a4 2.7620} {a5 0.7490} {a2 2.0300} {a15 113.1600}}
        {{a3 1.0995} {a5 0.3180} {a6 0.3395} {a7 0.5600} {a8 1.4035} {a9 1.1810} {a10 0.4340} {a11 0.3430} {a13 0.6970} {a14 208.1150} {a2 1.4630} {a4 1.0820}}
        {{a3 1.0995} {a5 0.3180} {a6 0.3395} {a7 0.5600} {a8 6.0835} {a9 1.1810} {a10 0.4340} {a11 0.3430} {a13 0.6970} {a14 208.1150} {a2 1.4630} {a4 1.0820}}
    }
    
    set maxima [lmap line $lines {
        set sorted [lsort -real -index 1 $line]
        set second_max [lindex $sorted end-1]
        if {[lindex $second_max end] <= 5.0} then continue else {set second_max}
    }]
    

    结果

    {a7 32.7832} {a8 6.0835}
    

    【讨论】:

      【解决方案4】:

      原始问题询问 Perl 或 TCL,所以这是一个可能的 Perl 解决方案

      my @lines = (
          "{a7 32.7832} {a8 1.6795} {a9 0.4920} {a10 0.6235} {a11 0.4190} {a14 3.2500} {a6 1.5170} {a12 0.2620} {a13 0.0410} {a3 2.6730} {a4 2.7620} {a5 0.7490} {a2 2.0300} {a15 113.1600}",
          "{a3 1.0995} {a5 0.3180} {a6 0.3395} {a7 0.5600} {a8 1.4035} {a9 1.1810} {a10 0.4340} {a11 0.3430} {a13 0.6970} {a14 208.1150} {a2 1.4630} {a4 1.0820}", 
          "{a3 1.0995} {a5 0.3180} {a6 0.3395} {a7 0.5600} {a8 6.0835} {a9 1.1810} {a10 0.4340} {a11 0.3430} {a13 0.6970} {a14 208.1150} {a2 1.4630} {a4 1.0820}",
      );
      
      
      for my $line (@lines)
      {
          my @data;
          print "
      new data
      ";
      
          # read & parse input data
          while ($line =~ /{(ad+)s+([d.]+?)}/g)
          {
              # don't want values less than 5
              next if $2 <= 5;
      
              # remember the values parsed
              push @data, [$1, $2];
          }
      
          # sort by the number
          @data = sort { $a->[1] <=> $b->[1] } @data;
      
          # don't want the biggest, so remove it
          pop @data;
      
          # now have the data to output
          print join " ", map { "{@$_}"   } @data ;
          print "
      " ;
      }
      

      产出

      new data
      {a7 32.7832}
      
      new data
      
      
      new data
      {a8 6.0835}
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-08
        • 1970-01-01
        • 2015-07-10
        • 1970-01-01
        • 2016-01-24
        相关资源
        最近更新 更多