找回密码
 加入
搜索
查看: 9843|回复: 24

[效率算法] 【已解決】二維數據組依條件判斷刪除一行問題 (關於_ArrayDelete應用)

 火.. [复制链接]
发表于 2011-6-22 01:22:20 | 显示全部楼层 |阅读模式
本帖最后由 kk_lee69 于 2011-6-22 13:34 编辑

已知  有一個二維數據組 資料 如下:
        姓名     成績
[0]    張三     85
[1]    李四     51
[2]    王五     65
[3]    劉六     34
[4]    林七     98

本來用循環........然後去 判斷  當 成績那邊的值<60 的時候  就利用_ArrayDelete 刪除整行

問題是 一刪掉以後  數據組的 整個結構就改變了......FOR 到最後會出問題.....況且判斷也會出問題

不知道是否 有更好的方法.....解決  求助各位高手......謝謝
发表于 2011-6-22 02:22:55 | 显示全部楼层
數據組的 整個結構----是什么意思,结构怎么会变
 楼主| 发表于 2011-6-22 03:00:07 | 显示全部楼层
不好意思 我在這邊在補充一下說明.......

For $i=1 TO UBound($fArray)-1 Step 1

        判斷 $fArray[$i][1] <60 的話  就 _ArrayDelete 刪除那行.....

Next

所以當 $i=1  得時候.....會把 那行刪除..... 這時候的陣列就會變成......

        姓名     成績
[0]    張三     85
[1]    王五     65
[2]    劉六     34
[3]    林七     98

所以當 本來 $i=1  所以刪除完畢後  $=2  這時  王五就沒有比對了........
而且 程式跑到 $i=4 的時候也會出問題吧.........

補充說明....... 上面那個陣列 其實是從EXCEL 讀取出來的.......
重點是 想把 成績小於60的人刪除  不要讀取到陣列裡面......

方法 一  先讀取全部....在陣列裡面處理......這是我現在的想法  遇到上面的問題
方法二   在EXCEL 裡面先處理好  在讀取........ 可是 EXCEL的操作我不熟  更困難
发表于 2011-6-22 04:25:08 | 显示全部楼层
还是不明白,你是要删除元素后原来的索引不变吗?只删数据,不删数据位?
发表于 2011-6-22 08:24:07 | 显示全部楼层
本帖最后由 happytc 于 2011-6-22 08:36 编辑

回复 3# kk_lee69
加个判断就可以了,其实这种最好用While..Wend或Do..Untile循环
因为For循环只是在第一次循环时读“步进值”和“ 停止值”,若你硬是要用For循环,也可以:

#include <Array.au3>

Local $Array[5][2] = [["張三", 85], ["李四", 51], ["王五", 65], ["劉六", 34], ["林七", 98]]
Local $ArrSize

_ArrayDisplay($Array)

$ArrSize = UBound($Array) - 1
For $i = 0 To UBound($Array) - 1
        If $i > $ArrSize Then ExitLoop
        
        If $Array[$i][1] < 60 Then 
                _Array2DDelete($Array, $i)
                $ArrSize -= 1
        EndIf
        
Next

_ArrayDisplay($Array)



;----------------------------------------------------------------------------------------------------------------------
;   Fuction         _Array2DDelete(ByRef $ARRAY, $iDEL, $bCOL=False)
;
;   Description     Delete one row on a given index in an 1D/2D -Array
;
;   Parameter       $ARRAY      the array, where one row will deleted
;                   $iDEL       Row(Column)-Index to delete
;                   $bCOL       If True, delete column instead of row (default False)
;  
;   Return          Succes      0   ByRef $ARRAY
;                   Failure     1   set @error = 1; given array are not array
;                                   set @error = 2; want delete column, but not 2D-array
;                                   set @error = 3; index is out of range
;
;----------------------------------------------------------------------------------------------------------------------
Func _Array2DDelete(ByRef $ARRAY, $iDEL, $bCOL=False)
    If ( Not IsArray($ARRAY) ) Then Return SetError(1,0,1)
    Local $UBound2nd = UBound($ARRAY,2), $k
    If $bCOL Then 
        If $UBound2nd = 0 Then Return SetError(2,0,1)
        If ( $iDEL < 0 ) Or ( $iDEL > $UBound2nd-1 ) Then Return SetError(3,0,1)
    Else
        If ( $iDEL < 0 ) Or ( $iDEL > UBound($ARRAY)-1 ) Then Return SetError(3,0,1)
    EndIf
    If $UBound2nd = 0 Then
        Local $arTmp[UBound($ARRAY)-1]
        $k = 0
        For $i = 0 To UBound($ARRAY)-1
            If $i <> $iDEL Then 
                $arTmp[$k] = $ARRAY[$i]
                $k += 1
            EndIf
        Next
    Else
        If $bCOL Then
            Local $arTmp[UBound($ARRAY)][$UBound2nd-1]
            For $i = 0 To UBound($ARRAY)-1
                $k = 0
                For $l = 0 To $UBound2nd-1
                    If $l <> $iDEL Then
                        $arTmp[$i][$k] = $ARRAY[$i][$l]
                        $k += 1
                    EndIf
                Next
            Next
        Else
            Local $arTmp[UBound($ARRAY)-1][$UBound2nd]
            $k = 0
            For $i = 0 To UBound($ARRAY)-1
                If $i <> $iDEL Then
                    For $l = 0 To $UBound2nd-1
                        $arTmp[$k][$l] = $ARRAY[$i][$l]
                    Next
                    $k += 1
                EndIf
            Next
        EndIf
    EndIf
    $ARRAY = $arTmp
    Return 0
EndFunc ;==>_Array2DDelete


用_ArrayDelete()为

#include <Array.au3>

Local $Array[5][2] = [["張三", 85], ["李四", 51], ["王五", 65], ["劉六", 34], ["林七", 98]]
Local $ArrSize

_ArrayDisplay($Array)

$ArrSize = UBound($Array) - 1
For $i = 0 To UBound($Array) - 1
        If $i > $ArrSize Then ExitLoop
        
        If $Array[$i][1] < 60 Then 
                _ArrayDelete($Array, $i)
                $ArrSize -= 1
        EndIf
        
Next

_ArrayDisplay($Array)
 楼主| 发表于 2011-6-22 08:44:58 | 显示全部楼层
还是不明白,你是要删除元素后原来的索引不变吗?只删数据,不删数据位?
netegg 发表于 2011-6-22 04:25



回覆蛋蛋老大

   我要刪除 數據以及 索引值.....但是 我用的語法....如同 Happytc 兄 所說的  
因为For循环只是在第一次循环时读“步进值”和“ 停止值”,

所以在RUN 的時候會出問題........我想要解決的就是這個問題......如何讓程式可以完成判斷....又不會漏掉任何比對......刪除 不符合規則的  數據以及索引值
发表于 2011-6-22 11:34:08 | 显示全部楼层
回复 6# kk_lee69
1、前面只判断是否大于60,把小于60的序号保存至另外的数组,当所有数据跑完之后,倒序删除小于60的元素
2、这个方法数组比较大的话不建议使用,用新建数组承载大于60的原数组元素,不要进行del操作,因为AU对数组的支持确实差强人意,所以不用非得按着一条路子走到底
3、我一贯建议大家多想思路,而不是多记代码,这个对编程的思想很重要,另外最简单的代码是针对自己问题设计的代码,所有的UDF设计之初都考虑到了要适应所有的代码环境而使代码显得很臃肿,这不是UDF的错,而是用UDF的人懒
发表于 2011-6-22 11:55:28 | 显示全部楼层
本帖最后由 3mile 于 2011-6-22 11:59 编辑

难道不能从尾序开始判断并删除?
#include <array.au3>
local $array[100][2]
for $i=0 to 99
        $array[$i][0]=ChrW(Random(19968,40869,1))&ChrW(Random(19968,40869,1))&ChrW(Random(19968,40869,1))
        $array[$i][1]=Random(1,100,1)
Next
_ArrayDisplay($array)
$k=UBound($array)-1
for $i=UBound($array)-1 to 0 step -1
        if $array[$i][1]<60 Then
                _ArrayDelete($array,$i)
                if $i<>$k Then $i+=1
        EndIf
Next

_ArrayDisplay($array)
 楼主| 发表于 2011-6-22 13:33:36 | 显示全部楼层
哈哈  3mile  老大的思路漂亮!!.........

今天我研究半天的結果也是這樣解決的.......

感謝 Happytc 兄 跟 3mile 的 範例....... 也感謝各位朋友的回覆....... 問題解決了!!
 楼主| 发表于 2011-6-22 13:41:33 | 显示全部楼层
再請教3mile 老大 一個問題  我看範例裡面有個
$k=UBound($array)-1     ====>  看不懂用意的第一行
for $i=UBound($array)-1 to 0 step -1
        if $array[$i][1]<60 Then
                _ArrayDelete($array,$i)
                if $i<>$k Then $i+=1    ====>看不懂用意的第二行
        EndIf
Next

上述兩行的用意 看不太懂.............
為何....要設一個變數$K  讓 $k=UBound($array)-1

然後又在循環裡面判斷  if $i<>$k Then $i+=1

3mile 老大  如果 用你的從後面開始判斷的邏輯來說......這兩行應該不需要吧
发表于 2011-6-22 13:55:21 | 显示全部楼层
回复 10# kk_lee69


    3mile也没有搞明白for循环时“起止变量”的内部用法

的确不需要那两行
 楼主| 发表于 2011-6-22 17:08:51 | 显示全部楼层
Happytc 兄  你的也有那兩行的用途.....但是是因為前提  是要從 0到 尾端的方式 去做 for  next

目的是為了跳脫迴圈  去做處理的吧 ...........我應該沒有理解錯誤吧

感謝提供技巧.......多學了一招
发表于 2011-6-22 17:38:07 | 显示全部楼层
回复 11# happytc
你错了,仔细看.
发表于 2011-6-22 19:06:44 | 显示全部楼层
本帖最后由 netegg 于 2011-6-22 20:31 编辑

回复 13# 3mile
三笑,这样是不是多算了一步,虽说影响不大,但如果100个成绩都小于60,岂不是要循环计算200次(我也没试可能想错了)

如果数组在删除后允许项目的索引变化,倒大可不必这么费事
#include <Array.au3>
Dim $Array[5][2] = [["張三", 85], ["李四", 51], ["王五", 65], ["劉六", 34], ["林七", 98]]
$index = _ArraySearch($Array, 60, 0, 0, 0, 0, 0, 1)
If @error Then
        ReDim $Array[6][2]
        $Array[5][0] = ''
        $Array[5][1] = 60
EndIf
_ArraySort($Array, 1,0,0,1)
$index = _Arrayfindall($Array, 60, 0, 0, 0, 0, 1)
ReDim $Array[$index[ubound($index)- 1]-1][2]
_arraydisplay($Array, ' ')
排序后删掉后面的部分就可以了
发表于 2011-6-22 19:12:55 | 显示全部楼层
我推翻刚才说的,建一个新的数组承载更好,因为本身del这个UDF就是数组重新排序,还不如直接重组的好
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-1 23:36 , Processed in 0.084877 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表