【问题标题】:How to scramble characters in a string?如何打乱字符串中的字符?
【发布时间】:2018-03-10 16:58:11
【问题描述】:

我正在编写一个读取文本文件的脚本。在标题行之后,我读取了数据行。在读入每个数据行时,AssetID 和 Description 列中的字符串值将被打乱。我在制表符分隔符上分割每一行。知道AssetID在数组位置1,Description在位置2,就可以得到字符串了。

我想知道一种打乱两个字符串的简单方法。这里有一些代码供参考。

附:现在我对循环进行了注释,以便我可以测试第一个标题行上的“加扰”,以确保它在我在整个项目中实施之前有效。

Const ForReading = 1

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("AssetImport.txt", ForReading)
Set objFile2 = objFSO.CreateTextFile("\newnewnew.txt")

Do Until objFile.AtEndOfStream
    strLine = objFile.ReadLine

    arrFields = Split(strLine, vbTab)

    If (UBound(arrFields) = 1) Then
        'script to write header lines here
        objFile2.WriteLine arrFields(0)
    Else
        'scramble AssetID and Description Columns, then write
        Randomize
        objFile2.WriteLine arrFields(0)
        arrFields(1) = Scramble(arrFields(1))
        objFile2.WriteLine arrFields(1)
        objFile2.WriteLine arrFields(2)
        objFile2.WriteLine arrFields(3)
        objFile2.WriteLine arrFields(4)
        arrFields(5) = Scramble(arrFields(5))
        objFile2.WriteLine arrFields(5)
        objFile2.WriteLine arrFields(6)
    End If
Loop

objFile.Close
objFile2.Close

Function Scramble(s)
    Dim i, j, n
    Dim temp, shuffled

    n = Len(s)
    ReDim shuffled(n - 1)
    For i = 1 To n
        shuffled(i - 1) = Mid(s, i, 1)
    Next

    For i = 0 To n - 2
        j = i + Int((n - i) * Rnd())
        temp = shuffled(i)
        shuffled(i) = shuffled(j)
        shuffled(j) = temp
    Next
    Scramble = Join(shuffled, "")

结束函数

【问题讨论】:

  • 能否请您添加一个txt文件示例?
  • txt 文件如下所示... headerline1 headerline2 headerline3 columnName1,columnName2...columnName7 data1 data2 data3 data4 data5 data6 data7 data1 data2 data3 data4 data5 data6 data7 data1 data2 data3 data4 data5 data6 data7 ... data1 data2 data3 data4 data5 data6 data7(文件结尾)
  • 加扰数据的目的是什么?你需要在某个时候解读它吗?
  • 这是个好问题,老实说我不知道​​打乱数据的原因。作为任务交给我完成。我没有放任何原始数据或文件位置,因为我不知道我是否有权这样做。谢谢!
  • 另外,在我注释的txt文件格式中,它没有注册我输入的换行符。所以每个标题行都是一个单独的行。并且每个数据(n)都是制表符分隔的,data1-data7 重复都在单独的“行”上。希望这会有所帮助!

标签: string random vbscript scramble


【解决方案1】:

您可以对字符串的字符进行Fisher-Yates shuffle:

Function Scramble(s)
    'Performs a Fisher-Yates Shuffle on the characters in the string
    'Assumes that Randomize has been called

    Dim i, j, n
    Dim temp, shuffled

    n = Len(s)
    ReDim shuffled(n - 1)
    For i = 1 To n
        shuffled(i - 1) = Mid(s, i, 1)
    Next

    'now do Fisher-Yates:
    For i = 0 To n - 2
        j = i + Int((n - i) * Rnd())
        temp = shuffled(i)
        shuffled(i) = shuffled(j)
        shuffled(j) = temp
    Next
    Scramble = Join(shuffled, "")

End Function

'test script:

Randomize
s = InputBox("Enter a word to be scrabled")
MsgBox Scramble(s)

【讨论】:

  • 谢谢约翰,做得很好!我的下标超出范围:“[编号:1]”错误。它位于“arrFields(1) = Scramble(arrFields(1))”行。在我写入的文本文件中,它写了第一个标题行,然后我得到了错误。在第一个标题行之后,它转到 else 而不是留在 if 中(前 3 行是标题行)。我不确定为什么会这样。我已经更新了代码供您查看。
  • @KeyurVaidya 也许问题是If (UBound(arrFields) = 1)应该被If (UBound(arrFields) <= 1)替换?如果上限为 0,您将在 else 子句中得到该错误。
  • 好点!这确实解决了我遇到的问题!再次感谢!
【解决方案2】:

我可能会这样做:

  1. 用字符串的字符填充字典,使用字符位置作为键。

    s = "..."   'string to scramble
    
    Set d = CreateObject("Scripting.Dictionary")
    For n = 1 To Len(s)
        d(n) = Mid(s, n, 1)
    Next
    
  2. 创建一个与字典中键/值对数量相同大小的数组。

    ReDim a(UBound(d.Keys))
    
  3. 选择一个随机键并将对应的项放入数组的下一个空闲槽中,然后删除键/值对。重复直到所有字符都被移动。

    Randomize
    For n = 0 To UBound(a)
        keys  = d.Keys
        index = Int((UBound(keys) + 1) * Rnd)  'pick random key
        a(n)  = d(keys(index))                 'copy corresponding value to array
        d.Remove(keys(index))                  'remove key/value pair
    Next
    

    使用keys 数组,以便可以通过(随机)索引选择剩余的键之一。

  4. 将数组连接回字符串:

    scrambled = Join(a, "")
    

【讨论】:

    猜你喜欢
    • 2015-05-02
    • 2011-04-26
    • 2023-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    相关资源
    最近更新 更多