通过python或Tcl增加字符串中的数字

时间:2015-05-04 18:14:57

标签: python arrays string integer tcl

我有一些带整数的字符串(一个字符串中的2到5个数字,用空格分隔)这是一个例子:

    1    4    5   19
    1    5
    2    3    6   59
    2    6
    3    2    4   60
    3    4
    4    1    3   61
    4    3
   25   13   23   64   65
   13   18
   14   13   15   75
   14   15
   15   14   16   76
   15   14
   45   44  102  103  104

我需要重复地将所有数字增加129,所以开头将是:

130  133  134 148
130  134
131  132  135 188  ...

接下来的增加将是:

259  262  263 277
259  263
260  261  264 317 ...

此类字符串分析的最佳选择是什么? 首先计算数字,然后使矩阵填充“0”:[0,0,0,0,0] 比填充它 - 它将是: 第1行[1,4,5,19, 0 ] 第2行[1,5, 0 0 0 ]

并增加所有不为零的数字。 我正在考虑正确方向的这项任务的解决方案还是有更简单的方法? 或者有任何现成的解决方案,我只是不明白如何准确搜索它?

结果必须采用特定格式 - it is PDB file CONECT records

6 个答案:

答案 0 :(得分:2)

如果您知道最终尺寸,则可以预先分配一个numpy数组的零。说出您最初要处理每一行的方式(SwingUtilities.invokeAndWait),然后对文件中的每一行(process_row)执行此操作。

process_file

答案 1 :(得分:2)

一个Tcl,如果你只需要加起来的数字:

set text {    1    4    5   19
    1    5
    2    3    6   59
    2    6
    3    2    4   60
    3    4
    4    1    3   61
    4    3
   25   13   23   64   65
   13   18
   14   13   15   75
   14   15
   15   14   16   76
   15   14
   45   44  102  103  104}

proc addevery {txt amount} {
    # Creating an alias so we can modify the variable from outside the proc
    upvar text gtext
    set result [list]
    # Split to get lines
    foreach line [split $txt \n] {
        set lineresult [list]
        # Get each number added
        foreach item [regexp -all -inline {\S+} $line] {
            lappend lineresult [expr {$item+$amount}]
        }
        lappend result $lineresult
    }
    set gtext [join $result \n]
    puts $gtext
    return
}

puts "Adding 129:"
addevery $text 129

puts "\nAdding again 129:"
addevery $text 129

ideone demo

编辑:在了解潜在问题之后;我们必须保持格式化(更具体地说,在每一系列数字之前添加CONECT,使数字保持5个空格右缩进格式,并能够输出添加到原始数据的不同“步骤”同一个文件中的数字。最后一件事,第一次迭代实际上不应该向原始数字添加任何东西。

set fin [open "Input.txt" r]
set fout [open "Output.txt" w]

set lines [split [read $fin] "\n"]

# Amount to be added each time
set amount 129
# Number of times to be added
set times 100

proc addevery {amount} {
  global lines
  # Result list
  set lresult [list]
  foreach line $lines {
    # Result line
    set result {}
    # Get every 5 chars of the line
    foreach item [regexp -all -inline {.{5}} $line] {
      # Add, format then append to result line
      append result [format %5s [expr {[string trim $item]+$amount}]]
    }
    # Add line to the result list
    lappend lresult $result
  }
  # Set the lines to the new lines
  set lines $lresult
  return $lresult
}

for {set i 0} {$i < $times} {incr i} {
  # If 0, put the original with CONECT
  if {$i == 0} {
    puts $fout [join [lmap x $lines {set x "CONECT$x"}] "\n"]
  } else {
    puts $fout [join [lmap x [addevery $amount] {set x "CONECT$x"}] "\n"]
  }
}

close $fin
close $fout

作为奖励,python相当于:

amount = 129
times = 100

import re

def addevery(amount):
  global lines
  lresult = []
  for line in lines:
    result = ''

    for item in re.findall(r'.{5}', line):
      result += "%5s" % (int(item.strip()) + amount)

    lresult.append(result)

  lines = list(lresult)
  return lresult

with open('Input.txt', 'r') as fin:
  with open('Output.txt', 'w') as fout:
    lines = fin.read().split('\n')
    for i in range(0,times):
      if i == 0:
        fout.write('\n'.join(['CONECT'+i for i in lines]) + '\n')
      else:
        fout.write('\n'.join(['CONECT'+i for i in addevery(amount)]) + '\n')

答案 2 :(得分:1)

你正在寻找一个二维数组(它是一个矩阵)。

首先,你可以用0来初始化它:

Matrix = [[0 for x in range(20)] for x in range(5)]

您必须更改所需尺寸的数量。 20是行数,5是列数。

之后,你可以将数字放在你想要的位置,使用:

Matrix[r][c] = 1

同样,R是行,C是列。

如果你想在开始时填充矩阵,你也可以选择:

Matrix = [ [1, 4, 5, 19, 0], [1, 5, 0, 0, 0], [0, 0, 0, 0, 0],
[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0] ]

然后在彼此内部使用两个for循环来增加数字

for i in range(20):
   for j in range(5):
      Matrix[i][j] = Matrix[i][j] + 129

答案 3 :(得分:1)

一些Tcl解决方案。假设带有数字的原始文本位于变量str中,请参见下文。

执行此操作的一种方法是将所有数字替换为命令调用以进行计算,然后对字符串执行替换(格式化将稍微关闭,因为数字现在会更宽,但空格保持不变):

set res [subst [regsub -all {\d+} $str {[expr {&+129}]}]]

另一种方法是将字符串拆分为行和数字的矩阵并遍历它:

set res {}
foreach line [split $str \n] {
    foreach n $line {
        append res [format %5s [incr n 129]]
    }
    append res \n
}

使用Tcl 8.6 lmap映射命令的相同方法:

set res [join [lmap line [split $str \n] {
    join [lmap n $line {
        format %5s [incr n 129]
    }] {}
}] \n]

在这两种情况下,结果字符串都将位于变量res中,并保留原始格式。

ETA:右对齐输出:

set res [join [lmap line [split $str \n] {
    format %25s [join [lmap n $line {
        format %5s [incr n 129]
    }] {}]
}] \n]

变量str像这样分配,作为纯文本(在末尾修剪换行符以避免空鬼元素):

set str [string trim {
    1    4    5   19
    1    5
    2    3    6   59
    2    6
    3    2    4   60
    3    4
    4    1    3   61
    4    3
   25   13   23   64   65
   13   18
   14   13   15   75
   14   15
   15   14   16   76
   15   14
   45   44  102  103  104
} \n]

文档:appendexprforeachformatincrlmapregsub,{{3 }},setsplitstring

答案 4 :(得分:1)

Tcl: requires Tcl 8.6 for lmap

package require Tcl 8.6

# list of strings
set strings {
    {    1    4    5   19}
    {    1    5}
    {    2    3    6   59}
    {    2    6}
    {    3    2    4   60}
    {    3    4}
    {    4    1    3   61}
    {    4    3}
    {   25   13   23   64   65}
    {   13   18}
    {   14   13   15   75}
    {   14   15}
    {   15   14   16   76}
    {   15   14}
    {   45   44  102  103  104}
}

proc incr_all {listvar {n 1}} {
    upvar 1 $listvar lst
    set lst [lmap sublist $lst {lmap elem $sublist {expr {$elem + $n}}}]
}

proc format_strings {lst} {
    join [lmap sublist $lst {format [string repeat {%5s} [llength $sublist]] {*}$sublist}] \n
}

incr_all strings 119
puts [format_strings $strings]

output

  120  123  124  138
  120  124
  121  122  125  178
  121  125
  122  121  123  179
  122  123
  123  120  122  180
  123  122
  144  132  142  183  184
  132  137
  133  132  134  194
  133  134
  134  133  135  195
  134  133
  164  163  221  222  223

答案 5 :(得分:1)

set incriment 127
set molecules 450
set fout [open "Results.txt" w]
close $fout

proc addevery {filein fileout amount times} {
  set fh [open $filein r]
  set fout [open $fileout a+]
  while {[gets $fh line] != -1} {
    set result {}
    foreach item [regexp -all -inline {.{5}} $line] {
      append result [format %5s [expr {[string trim $item]+($amount*$times)}]]
    }
    puts $fout "CONECT$result"
  }
  close $fh
  close $fout
}

for {set i 0} {$i < $molecules} {incr i} {
    addevery "Connections_.txt" "Results.txt" $incriment $i
}

感谢https://stackoverflow.com/users/1578604/jerry 它工作正常,但尚未优化。