Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 排序重复字符串的最快方法是什么_String_Vb.net_Duplicates - Fatal编程技术网

String 排序重复字符串的最快方法是什么

String 排序重复字符串的最快方法是什么,string,vb.net,duplicates,String,Vb.net,Duplicates,我正在开发一个应用程序,它以各种方式处理字符串。其中之一是在合并文件时删除任何重复项。 我已尝试使用此选项: Private Sub run() For Each filePath As String In ListBox1.Items For Each Line In IO.File.ReadAllLines(filePath) Dim founds() As String = Line.Split(":") Dim ha

我正在开发一个应用程序,它以各种方式处理字符串。其中之一是在合并文件时删除任何重复项。 我已尝试使用此选项:

Private Sub run()
    For Each filePath As String In ListBox1.Items
        For Each Line In IO.File.ReadAllLines(filePath)
            Dim founds() As String = Line.Split(":")
            Dim hash As String = founds(0)
            Dim word As String = founds(1)
            foundList.Add(word)
            Dim result As List(Of String) = foundList.Distinct().ToList
            Label1.Text = result.Count
            For Each addstring In result
                ListBox2.Items.Add(addstring)
            Next
        Next
    Next
End Sub
Distinct在这种方式下速度非常慢,因此我尝试使用:

Private Sub run()
    For Each filePath As String In ListBox1.Items
        For Each Line In IO.File.ReadAllLines(filePath)
            Dim founds() As String = Line.Split(":")
            Dim hash As String = founds(0)
            Dim word As String = founds(1)

            If Not foundList.Contains(word) Then
                foundList.Add(word)
                Label1.Text = foundList.Count
            End If
        Next
    Next
    For Each found In foundList
        ListBox2.Items.Add(found)
    Next
End Sub
这要快得多,但是执行速度仍然比不使用OpenCL或类似工具时要慢。我可以用C#写,如果有什么不同的东西,除了这个在.NET中。 有人能提出一种更快或更有效的方法吗? 不可能是这样,我肯定遗漏了什么。

使用
哈希集(字符串)

初始化后,
HashSet
将包含唯一值。
您可以使用
HashSet(Of T).Add(value)
方法-如果值被添加到集合中,则返回
true
,如果值已经存在于集合中,则返回
false

Dim isAdded As Boolean = uniqueLines.Add("someValue")
If isAdded Then
    ' Do something if added
Else
    ' Do something if already exists
End if
HashSet
have-method
Contains
哪个算法是O(1)-使用固定数量的运算,例如
List。Contains
方法将迭代整个列表,直到找到给定的值(O(N)-运算量等于值情况下的项目数量)

因此,您的函数可以按如下方式重新编写

Private Sub run()
    ' get data
    Dim allItems = ListBox1.Items.
                            SelectMany(Function(path) IO.File.ReadAllLines(path)).
                            SelectMany(Function(line) Line.Split(":"))
    Dim uniqueItems = New HashSet(Of String)(allItems)

    ' update controls
    Label1.Text = uniqueItems.Count.ToString()
    ListBox2.Items.AddRange(uniqueItems.ToArray())
End Sub

请注意,使用
.AddRange
方法将项目添加到
列表框2
。此方法将在一次操作中添加项,并仅重新绘制控件一次。当你一个接一个地添加项目时(使用
.Add
方法),你可以控制为每个添加的项目重新绘制自己,这对于大量的项目来说可能是“沉重的”。

Fabio在我完成之前得到了明显的答案。我已经介绍了更多细节,但请跳到底部了解另一个想法


明显的速度问题在于字符串比较:

If Not foundList.Contains(word) Then
比较字符串是一个相当昂贵的操作,在这里,您将字符串与其他字符串的连续较大列表进行比较。对于一个简短的列表,这可能是好的,但当你处理大的列表时,它会慢一些

更好的选择是将每个字符串散列一次,然后比较散列。需要处理一些技巧,但是当大量数据是唯一的并且散列函数很好时,速度会有很大的提高

在.NET中,该类实现了基于哈希的存储和查找

作为一个集合,
HashSet
将只保存任何特定值中的一个,用于处理复制问题。它不保证保留其内容的顺序,但在实践中,如果您只添加而从不删除项目,则顺序将被保留

由于散列值在内部的存储和索引方式,在
散列集中的查找速度非常快。测试以查看集合中是否存在值几乎不受列表中项目数的影响。通过一个简单的测试(100000000次查找),我在1000到1000000个字符串的列表中得到大约50ns的查找时间

出于您的目的,用法类似于(在C中):

(对不起,VB不是我的母语。)


问题是,这真的会加快速度吗?你需要自己做一些测试,但我怀疑答案可能是:不多

是的,它比使用
Distinct
ToArray
获取排序值数组更快。通过我的简单测试,速度几乎是原来的两倍~对于数组中100万个不同的36个字符的字符串(是的,它们是GUID),使用180ms到275ms。增幅不大。YMMV,但如果操作所花费的时间远远超过此值,则
Distinct
可能不是您最大的问题

做一些分析,找出真正的痛点。我怀疑您会发现
ListBox2
设置了
Sorted
标志。请尝试以下操作(抱歉,请在C#中重试):

Private子运行()
{
Dim items=ListBox1.items.Of类型(字符串)()。
选择many(函数(fn)File.ReadAllLines(fn))。
选择(功能(i)i.Split(“:”c)(1))
Dim hash=HashSet(项目)
ListBox2.Items.Clear()
Dim sorted=ListBox2.已排序
ListBox2.Sorted=false
ListBox2.Items.AddRange(hash.ToArray())
ListBox2.Sorted=已排序
}
如果这要快得多,那么问题不在
Distinct
中,而是在插入时排序,它的速度非常慢,几乎总是排序列表的最差选项


如果不是,则问题可能是在使用
Distinct
并添加它们之前获取所有值(最慢的部分仍在更新控件):


Distinct()
很慢,因为您对每个文件中的每一行都调用它。相反,建立您的
foundList
,然后在其上调用
Distinct()
。同样,在每个文件的每一行填充列表框。正如你所能想象的,这对性能来说是可怕的。仅填充列表一次。。在你有了明确的清单之后。这看起来很简单,但对我来说仍然是新的。我在将此应用于我的表格时遇到了一些问题。@King96,您能描述一下您在使用此方法时面临的问题吗?我不知道如何将您的问题与我的问题结合起来。当我尝试时,到处都会收到错误。不过现在正在阅读hashSet的更多内容。我很快会再试一次。尽管如此,还是要谢谢你。对于这种特殊情况,没有什么有用的东西。哇,这是一个非常详细的解释。非常感谢您抽出时间回答。我对你的答案投了赞成票,并将在第二天早上进一步测试后做出选择。再次感谢您的解释。若要转换为VB,请将
private void
更改为
private Sub
,移除开始大括号,将结束大括号更改为
End Sub
,将
var
更改为
Dim
,将
更改为
(字符串的)
,将
=/code>更改为
函数(),将
':'
更改为
':“c
,将
[1]
更改为
(1)
,并删除此处的分号
If Not foundList.Contains(word) Then
Private Sub Run()
    ' shortcut the file reads...
    Dim items = ListBox1.Items.OfType(Of String)()
        .SelectMany(Function(fn) File.ReadAllLines(fn))
        .Select(Function(i) i.Split(":"c)(1))
    Dim hash = New HashSet(Of String)(items)
    ListBox2.Items.Clear()
    ListBox2.Items.AddRange(hash.ToArray())
End Sub
Private Sub Run()
{
    Dim items = ListBox1.Items.OfType(Of String)().
        SelectMany(Function(fn) File.ReadAllLines(fn)).
        Select(Function(i) i.Split(":"c)(1))
    Dim hash = HashSet<string>(items)
    ListBox2.Items.Clear()
    Dim sorted = ListBox2.Sorted
    ListBox2.Sorted = false
    ListBox2.Items.AddRange(hash.ToArray())
    ListBox2.Sorted = sorted
}
ListBox2.DataSource = (From line In IO.File.ReadLines(filePath) 
                       Select line.Split(":"c)(1) Distinct).ToList