3mile 发表于 2010-11-13 16:16:13

回复 30# binghc
加个判断应该可以了.
不使用Redim函数应该可以提高些效率.
#include <array.au3>
#include <file.au3>

Local $aArray,$time=TimerInit()
_FileReadToArray('test.txt',$aArray)
Global $count=$aArray
_ArrayDelete($aArray,0);删除总行数,避免排序出错
$aa = _unique($aArray)
MsgBox(0,'用时:'&TimerDiff($time),'总行数:'&$count)
_ArrayDisplay($aa)

Func _unique($aArray)
    If Not IsArray($aArray) Then Return SetError(1);非数组
    Local $rows = UBound($aArray), $cols = UBound($aArray, 2), $dims = UBound($aArray, 0)
    If $dims > 2 Then Return SetError(2);非一维或二维数组
    If $dims = 2 Then
      Local $temp[$rows][$cols + 1]
      For $n = 0 To $cols
            If $n < $cols Then
                For $i = 0 To $rows - 1
                  $temp[$i][$n] = $aArray[$i][$n]
                Next
            Else
                For $i = 0 To $rows - 1
                  $temp[$i][$n] = $i
                Next
                ;_ArrayDisplay($temp)
            EndIf
      Next
      _ArraySort($temp)
      For $i = 1 To $rows - 1
            If $temp[$i] == $temp[$i - 1] Then $temp[$i - 1][$cols] = -1
      Next
      _ArraySort($temp, 0, 0, 0, $cols)
      Local $k = 0, $y = 0, $p = 0, $reules[$cols]
      For $n = 0 To $cols - 1
            For $i = 1 To $rows - 1
                If $temp[$i][$cols] > -1 Then
                  $p = UBound($reules)
                  ReDim $reules[$p + 1][$cols]
                  $reules[$k][$n] = $temp[$i][$n]
                  $k += 1
                  If $reules[$p - 1] == '' Then _ArrayDelete($reules, $p - 1)
                EndIf
            Next
            $k = $y
            $y += 1
      Next
      _ArrayDelete($reules, UBound($reules) - 1)
      Return $reules
    Else
      Local $temp[$rows];,$k=$count,$p=0
      For $i = 0 To $rows - 1
            $temp[$i] = $aArray[$i]
            $temp[$i] = $i
      Next
      _ArraySort($temp)
      For $i = 1 To UBound($temp) - 1
            If $temp[$i] == $temp[$i - 1] Then
                $min=_Min($temp[$i],$temp[$i - 1])
                $temp[$min] = -1
                ;$k-=1
            EndIf
      Next
      _ArraySort($temp, 0, 0, 0, 1)
      Local $k=$count
      For $i=0 To UBound($temp)-1
            If $temp[$i]=-1 Then $k-=1
      Next
      Local $reules[$k+1],$p
      For $i=0 To UBound($temp)-1
            If $temp[$i]=-1 Then ContinueLoop
            $reules[$p]=$temp[$i]
            $p+=1
      Next
      Return $reules
    EndIf
EndFunc   ;==>_unique

Func _Min($nNum1, $nNum2)
    If (Not IsNumber($nNum1)) Then Return SetError(1, 0, 0)
    If (Not IsNumber($nNum2)) Then Return SetError(2, 0, 0)

    If $nNum1 > $nNum2 Then
      Return $nNum2
    Else
      Return $nNum1
    EndIf
EndFunc   ;==>_Min

binghc 发表于 2010-11-13 16:26:29

本帖最后由 binghc 于 2010-11-13 16:30 编辑

回复 31# 3mile


嗯,没错,是比上一个快了点,但是。。。。
我纳闷了,你这是要什么效果?




3mile 发表于 2010-11-13 16:35:15

回复 32# binghc
哈哈,我自己也郁闷了.
正在修改中,想法大概有了吧.
顺便请你将测试文本也发上来吧.

binghc 发表于 2010-11-13 16:43:43

本帖最后由 binghc 于 2010-11-13 16:44 编辑

回复 33# 3mile


嗯,好!就是这本小说,怕扣钱也可以自己网上下载,这是小说原文本,没改。测试的时候自己稍微改一下


3mile 发表于 2010-11-13 17:59:22

回复 34# binghc
请帮忙再测试下吧.多谢
但是效率应该下降了些.
#include <array.au3>
#include <file.au3>

Local $aArray,$time=TimerInit()
_FileReadToArray('萌动校园.txt',$aArray)
Global $count=$aArray
_ArrayDelete($aArray,0);删除总行数,避免排序出错
$aa = _unique($aArray)
MsgBox(0,'用时:'&TimerDiff($time),'总行数:'&$count)
_FileWriteFromArray('输出.txt',$aa)
_ArrayDisplay($aa)

Func _unique($aArray)
    If Not IsArray($aArray) Then Return SetError(1);非数组
    Local $rows = UBound($aArray), $cols = UBound($aArray, 2), $dims = UBound($aArray, 0)
    If $dims > 2 Then Return SetError(2);非一维或二维数组
    If $dims = 2 Then
      Local $temp[$rows][$cols + 1]
      For $n = 0 To $cols
            If $n < $cols Then
                For $i = 0 To $rows - 1
                  $temp[$i][$n] = $aArray[$i][$n]
                Next
            Else
                For $i = 0 To $rows - 1
                  $temp[$i][$n] = $i
                Next
                ;_ArrayDisplay($temp)
            EndIf
      Next
      _ArraySort($temp)
      For $i = 1 To $rows - 1
            If $temp[$i] == $temp[$i - 1] Then $temp[$i - 1][$cols] = -1
      Next
      _ArraySort($temp, 0, 0, 0, $cols)
      Local $k = 0, $y = 0, $p = 0, $reules[$cols]
      For $n = 0 To $cols - 1
            For $i = 1 To $rows - 1
                If $temp[$i][$cols] > -1 Then
                  $p = UBound($reules)
                  ReDim $reules[$p + 1][$cols]
                  $reules[$k][$n] = $temp[$i][$n]
                  $k += 1
                  If $reules[$p - 1] == '' Then _ArrayDelete($reules, $p - 1)
                EndIf
            Next
            $k = $y
            $y += 1
      Next
      _ArrayDelete($reules, UBound($reules) - 1)
      Return $reules
    Else
      Local $temp[$rows];,$k=$count,$p=0
      For $i = 0 To $rows - 1
            $temp[$i] = $aArray[$i]
            $temp[$i] = $i
      Next
      _ArraySort($temp)
      For $i = 1 To UBound($temp) - 1
            If $temp[$i] == $temp[$i - 1] Then
                If $temp[$i]>$temp[$i - 1] Then
                  _ArrayDelete($temp,$i)
                  $i-=1
                Else
                  _ArrayDelete($temp,$i-1)
                  $i-=1
                EndIf
            EndIf
            If $i=UBound($temp)-1 Then ExitLoop
      Next
      _ArraySort($temp, 0, 0, 0, 1)
      Local $reules,$p
      For $i=0 To UBound($temp)-1
            If $temp[$i]=-1 Then ContinueLoop
            $reules[$p]=$temp[$i]
            $p+=1
      Next
      Return $reules
    EndIf
EndFunc   ;==>_unique

Func _Min($nNum1, $nNum2)
    If (Not IsNumber($nNum1)) Then Return SetError(1, 0, 0)
    If (Not IsNumber($nNum2)) Then Return SetError(2, 0, 0)

    If $nNum1 > $nNum2 Then
      Return $nNum2
    Else
      Return $nNum1
    EndIf
EndFunc   ;==>_Min

Func _Max($nNum1, $nNum2)
    ; Check to see if the parameters are indeed numbers of some sort.
    If Not IsNumber($nNum1) Then Return SetError(1, 0, 0)
    If Not IsNumber($nNum2) Then Return SetError(2, 0, 0)

    If $nNum1 > $nNum2 Then
      Return $nNum1
    Else
      Return $nNum2
    EndIf
EndFunc   ;==>_Max

binghc 发表于 2010-11-13 18:26:06

回复 35# 3mile


    现在基本上没问题(网速慢上传不了图片),'萌动校园.txt'这本小说,你用这个处理需多长时间啊?

(现在可以去处理一下我之前说的不能处理的向同行)
萌动校园
萌动校园ooo

binghc 发表于 2010-11-13 18:35:59

数组插入排序法确实是很快,我刚才还是发现了:
文中有很多相同的行,不是重复的,比如:    “……”
你找找看,像这种的话就属于误删了
这种算法是对数组进行排序,再处理,所以速度要快很多
但是如果要做到非相邻行相同不删除,也就是说只删除相同相邻行
能不能做到呢,这种算法?

3mile 发表于 2010-11-13 20:20:07

回复 37# binghc
刚才是单位的电脑,现在已经下班,没法测试时间了。
用家里的电脑测了下,配置是X2 4400+,2G内存。测试“萌动校园”小说用时10447毫秒,大约10秒多11秒吧。

如果要做到非相邻行相同不删除,也就是说只删除相同相邻行的话只用_ArrayDelete吧。

binghc 发表于 2010-11-13 21:00:09

看来我的电脑比你好啊,哈哈!我用了9秒,我用自己的代码测试用了10秒。不过单位电脑比你单位垃圾多了

3mile 发表于 2010-11-13 22:28:31

回复 39# binghc
呵呵,你那个代码我用了12秒。
几千行数据要处理,不在乎那几秒钟的时间。

afan 发表于 2010-11-13 22:34:23

本帖最后由 afan 于 2010-11-13 22:42 编辑

回复 40# 3mile


    用正则估计不会超过一秒,不过,此题没啥实用意义的说~ 如果是小说之类的,重复行(段)是完全可能正常存在的,用在这里肯定不合适~
倒是仅删除所有的重复行可能会有用,用P版在24#所说的方法或使用正则应该比用数组操作快许多倍~

3mile 发表于 2010-11-13 22:44:33

回复 41# afan
呵呵,确实没啥意义啊。
只是比较郁闷楼主所说的30多M的大文本哈。

afan 发表于 2010-11-13 22:52:36

回复 42# 3mile


    呵呵 貌似LZ都不关心本帖,倒是大家十分热心~

binghc 发表于 2010-11-13 23:16:29

本帖最后由 binghc 于 2010-11-13 23:19 编辑

呵呵,我们也不知道楼主是啥意思,他说有两个文件,我问了,他也没说

我们现在视乎在借楼主的提问,衍生到另外一个话题。由一开始的相邻重复行到相邻重复段,

然后又是非相邻的重复。

不过看了“三笑”兄的代码,本人现在对数组的排序算法倒是很感兴趣,虽然以前在学校学过一

点数组排序算法,现在有点陌生。研究了大半天,现在终于有点明白_arraysort()这个函数的数组排序算法

是怎么回事,现在继续研究。。。。。{:face (270):}

顺便发一下感慨:通过别人的代码读别人的思想真的是一件令人头疼的事!

nbmpe 发表于 2010-11-14 11:31:56

不是不热心,这个周末时间不多呀,我处理的文档是这样的,这把下面的复制一千次就行了。处理后的结果是下面的内容。
AAA BBB
CCC AAA
AB AB AC
ABCDE AAA
页: 1 2 [3] 4 5 6 7 8
查看完整版本: 删除重复行,为什么速度慢,帮看下代码(已解决)