Tech Off Thread

14 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

VisualBasic has bad arithmetic

Back to Forum: Tech Off
  • User profile image
    W3bbo

    Say it ain't so!

    But this simple procedure to remove duplicates from an arraylist:

            For i As Integer = 0 To (Categories.Count - 1)
                
                OK = False
                
                If Not  (i >= (Categories.Count - 1)) Then
                
                    Do Until OK
                            
               
            If Categories(i) = Categories(i +
    1)
                            
               
               
    Categories.RemoveAt(i + 1)
                            
                        Else
                            OK = True
                            
                        End If
                        
                    Loop
                
                End If
                
            Next
    


    ...Fails.

    Where Categories is an ArrayList containing an alphabetically stored array of strings.

    For instance, suppose Categories.Count = 61. So the highest index is 60, VB ignores the "If Not i >= Categories.Count - 1"

    Of course, I managed to hack my way around that with this:

            For i As Integer = 0 To (Categories.Count - 1)
                
                OK = False
                
                If Not (i >= (Categories.Count - 1)) Then
                
                    Do Until OK
                            
                        If Not (i + 1) = Categories.Count
                            
               
                If
    Categories(i) = Categories(i + 1)
               
               
               
                
               
               
            Categories.RemoveAt(i + 1)
                            
                            Else
               
               
        OK = True
               
               
        
                            End If
                        
                        Else
                        
                            Exit For
                        
                        End If
                        
                    Loop
                
                End If
                
            Next
    


    But it clearly needs a bit of optimisation. Any suggestions?

  • User profile image
    Sven Groot

    VB doesn't ignore it, your code is wrong. If the last two items are equal, the do loop will be repeated and therefore fail on i+1.

  • User profile image
    Mike Dimmick

    VB.NET re-evaluates the 'To' part at the top of each iteration. You're removing entries from the list, thus reducing Count.

    I'm assuming that all duplicates are contiguous - that seems to be the implication of your code. Therefore I'd write:

    i = 0

    ' Stop at one off the end as the previous iteration
    ' will have compared the last item already
    While i < Categories.Count - 1

    If Categories(i) = Categories(i + 1) Then
    Categories.RemoveAt(i + 1)
    Else
    ' Different, move to next candidate
    i += 1
    End If

    Wend

  • User profile image
    Sven Groot

    VB6 alert! It's not Wend, it's End While! Tongue Out

  • User profile image
    Rossj

    W3bbo wrote:
    If Not i >= Categories.Count - 1


    Am I the only person in the world who wonders if W3bbo's logic is arse-about-face?

  • User profile image
    nightski

    My question - why have this procedure in the first place?  Why not design the collection so that it implements "set" like behaviour and doesn't add duplicates.

  • User profile image
    nightski

    Rossj,
    Simply put - no Smiley  It makes no sense whatsoever.

  • User profile image
    Tensor

    Where is that refactoring tool when I need it?
     
    Guard clauses man, Guard clauses!

  • User profile image
    W3bbo

    Well, you can ignore this topic complete, I rewrote that segment a while ago.

    Comments?

    Public Class DirConts
    
        Public Shared Sub GetAllFilenamesFromFolder(ByVal
    Folder As String, ByRef refCategories As ArrayList, ByRef refFilenames
    As String() )
            
            Dim
    DirectoryInfo        As New
    System.IO.DirectoryInfo(Folder)
            Dim
    TheContents          As
    System.IO.FileInfo()
            TheContents = DirectoryInfo.GetFiles("*-*")
            
            Dim FileCount            As Integer
            FileCount = TheContents.GetUpperBound(0)
            
            Dim Filenames(FileCount) As String
            Dim
    Categories          
    As New System.Collections.ArrayList(FileCount)
            
            Dim CategoryNameIdx      As Int16
            Dim CategoryName         As String
            
            For i As Integer = 0 To FileCount
                
                Filenames(i) = TheContents(i).Name
                
                CategoryNameIdx = InStr(TheContents(i).Name, "-") - 1
                
                CategoryName = TheContents(i).Name.Substring(0, CategoryNameIdx)
                
                Categories.Insert(i, CategoryName)
                
            Next
            
            Dim CategoriesIndexes As New System.Collections.ArrayList()
            
            For i As Integer = (Categories.Count - 1) To 0 Step - 1
            
            
                If i >= 1 Then
                
                    If Categories(i) = Categories(i - 1) Then
                        
                        Categories.RemoveAt(i - 1)
                        
                    Else
                        
                        Dim Category As New Category
                        Category.Index = i
                        Category.Name = Categories(i)
                        
                        CategoriesIndexes.Add( Category )
                            
                    End If
                    
                Else
                
                    Dim Category As New Category
                    Category.Index = i
                    Category.Name = Categories(i)
                    
                    CategoriesIndexes.Add( Category )
                
                End If
                
            Next
            
            refCategories = CategoriesIndexes
            refFilenames  = Filenames
            
        End Sub
        
        Public Shared Function GetIconForFilename(ByVal strPath As String) As String
            Dim strExt As String
            Dim strIcon As String
            If InStr(1, strPath.ToString, ".") <> 0 Then
                strExt = Mid(strPath, InStrRev(strPath, ".") + 1).ToLower
            End If
            Select Case Replace(LCase(strExt), ".", "")
                Case "htm", "tml", "html"
                    strIcon = "html"
                Case "png"
                    strIcon = "gif"
                Case "gz"
                    strIcon = "rar"
                Case "config"
                    strIcon = "cfg"
                Case "txt"
                    strIcon = "text"
                Case "aspx"
                    strIcon = "asp"
                Case "wav", "mp3", "mid", "wma", "wmv", "mpg", "mpeg"
                    strIcon = "wmf"
                Case Else
                    strIcon = strExt
            End Select
            If InStr("jpg gif asp aspx bmp
    cfg css fla swf htm tml psd zip rar gz doc xls txt exe wav mp3 mid wma
    wmv mpg peg fig", strExt) = False Then
                strIcon = "unknown"
            End If
            Return "http://www.w3bdevil.com/fso/" & strIcon & ".gif"
            
        End Function
        
        Public Shared Function ReturnType(ByVal strExt As String) As String
            Select Case Replace(LCase(strExt), ".", "")
                Case "jpg", "jpeg", "jfif"
                    Return "JPEG Image"
                Case "gif"
                    Return "GIF Image"
                Case "png"
                    Return "PNG Image"
                Case "asp"
                    Return "Active Server Page"
                Case "aspx"
                    Return "ASP.Net Web Forms Page"
                Case "bmp"
                    Return "Bitmapped Image"
                Case "mp3"
                    Return "MP3 Audio File"
                Case "htm", "html"
                    Return "Hypertext Markup File"
                Case "swf"
                    Return "Macromedia Flash Animation"
                Case "zip", "rar", "gz"    
                    Return "Compressed Archive"
                Case "xls"
                    Return "Microsoft Excel Workbook"
                Case "doc"
                    Return "Microsoft Word Document"
                Case "exe"
                    Return "Executable"
                Case "txt"
                    Return "Plain Text"
                Case "rtf"
                    Return "Rich Text"
                Case "psd"
                    Return "Adobe Photoshop Document"
                Case "pdf"
                    Return "Adobe Acrobat Document"
                Case "wma", "wmv", "asx"
                    Return "Windows Media File"
                Case "mpeg", "avi", "mpg", "dv"
                    Return "Video File"
                Case Else
                    Return strExt & " file"
            End Select
        End Function
        
        Public Shared Sub GenerateListMain(ByRef SB As
    System.Text.StringBuilder, ByRef Categories As ArrayList, ByRef
    Filenames As String())
            
            Dim Even As Boolean = False
            
            For i As Integer = 0 To Filenames.GetUpperBound(0)
                
                If Even = True Then
                    SB.Append("<li class=""c0""")
                Else
                    SB.Append("<li class=""c1""")
                End If
                
                For j As Integer = 0 To (Categories.Count - 1)
                    
                    If Categories(j).Index = i Then
                        
               
            SB.Append(" id=""" &
    Categories(j).Name & """")
                        
                    End If
                    
                Next
                
                SB.Append(">")
                
               
    SB.Append("<a href=""" & Filenames(i) & """>" &
    Filenames(i) & "</a></li>" & vbCRLF)
                
                If Even = True Then
                    Even = False
                Else
                    Even = True
                End If
                
            Next
            
        End Sub
        
        Public Shared Sub GenerateListNav(ByRef SB As System.Text.StringBuilder, ByRef Categories As ArrayList)
            
            Dim Even As Boolean = False
            
            For i As Integer = (Categories.Count - 1) To 0 Step -1
            
                If Even = True Then
                    SB.Append("<li class=""c0"">")
                Else
                    SB.Append("<li class=""c1"">")
                End If
                
               
    SB.Append("<a href=""#" & Categories(i).Name & """>"
    & Categories(i).Name & "</a></li>" & vbCRLF)
                
                Even = Not Even
                
            Next
            
        End Sub
        
        Public Shared Sub GetContentsOfNormalFolder(ByRef SB
    As System.Text.StringBuilder, ByVal FolderPath As String, ByVal
    SearchPattern As String)
            
            Dim DirectoryInfo  As New System.IO.DirectoryInfo(FolderPath)
            Dim TheContents    As System.IO.FileInfo()
            TheContents = DirectoryInfo.GetFiles(SearchPattern)
            
            Dim Even As Boolean = False
            
            For i As Integer = 0 To TheContents.GetUpperBound(0)
                
                If Even = True Then
                    SB.Append("<li class=""c0"">")
                Else
                    SB.Append("<li class=""c1"">")
                End If
                
               
    SB.Append("<a href=""" & TheContents(i).Name & """>"
    & TheContents(i).Name & "</a></li>" & vbCRLF)
                
                Even = Not Even
                
            Next
            
        End Sub
        
    End Class
    
    Public Structure Category
        Public Index As Integer
        Public Name As String
    End Structure
    

  • User profile image
    Tensor

    I think I see what its doing.

    We have a saying in my office, gleefuly stolen from Michael Howards previous attempt to become Tory leader. When code looks like it was done in VB6, we say it has "Somthing of the module" about it. Theres nothing wrong with that, but a bit of refactoring could help improve readability and quality.

    Just stuff like InStr - nothing wrong with it, but I'd use String.IndexOf these days.

    Are you using vs 2005 beta 2? If so get the free Refactor! plug in. Its fantastic. I have to resist the urge to make "ping" "zoom" and "Woooooof" noises out loud when using it.

  • User profile image
    W3bbo

    Tensor wrote:
    Just stuff like InStr - nothing wrong with it, but I'd use String.IndexOf these days.


    ...why didn't anyone tell me that method existed?! GAH!

  • User profile image
    Tensor

    I think all the old VB string manipulation stuff can be replaced by String.SomeMethod

  • User profile image
    leighsword

    Mike Dimmick wrote:
    VB.NET re-evaluates the 'To' part at the top of each iteration. You're removing entries from the list, thus reducing Count.

    I'm assuming that all duplicates are contiguous - that seems to be the implication of your code. Therefore I'd write:


    i = 0

    ' Stop at one off the end as the previous iteration
    ' will have compared the last item already
    While i < Categories.Count - 1

       If Categories(i) = Categories(i + 1) Then
          Categories.RemoveAt(i + 1)
       Else
          ' Different, move to next candidate
          i += 1
       End If

    Wend
     

    //the fastest algorithm in the world
    int aryFoo[13];
        aryFoo[0] = 1;
        aryFoo[1] = 2;
        aryFoo[2] = 3;
        aryFoo[3] = 1;
        aryFoo[4] = 1;
        aryFoo[5] = 9;
        aryFoo[6] = 1;
        aryFoo[7] = 1;
        aryFoo[8] = 4;
        aryFoo[9] = 3;
        aryFoo[10] = 9;
        aryFoo[11] = 1;
        aryFoo[12] = 2;

        int first = 0;
        int next = 1;
        map<int , int> mapFoo;
        while(sizeof(aryFoo) != next){
            if(aryFoo[first] == aryFoo[next] || mapFoo.find(aryFoo[next]) != mapFoo.end())
                aryFoo[next++] = -1;    //set delete flag        
            else{
                mapFoo[aryFoo[first]]=1;
                first = next++;        
                
            }
        }
        
        for(int i=0; i<13; i++){
            cout << aryFoo[i];
        }

  • User profile image
    lorad

    Ok I was bored waiting on a build. Here is how I would have done parts of what you did up there. I built a small lookup table, it would allow you to add extensions etc at one place. It also allowed me to locate a few items that seemed to do the wrong thing for icons (they have "unknown" in the lookup table) and the lookup table is sorted so even easier to locate a missing extension etc. You will notice my category build code is makeing the same assumption you did, that the categories will be in sorted order, so I don't add one if I added it the last time I added a category, if not I assume it is a new category. Note I did not compile this so there may be an error, but should be easy to fix Smiley



        Public Shared Sub GetAllFilenamesFromFolder(ByVal Folder As String, ByRef refCategories As ArrayList, ByRef refFilenames As String() )
     
            Dim DirectoryInfo        As New System.IO.DirectoryInfo(Folder)
            Dim TheContents          As System.IO.FileInfo()
            TheContents = DirectoryInfo.GetFiles("*-*")
     
            Dim FileCount            As Integer
            FileCount = TheContents.GetUpperBound(0)
     
            Dim Filenames(FileCount)    As String
            Dim Categories              As New System.Collections.ArrayList(FileCount)
     
            Dim CategoryNameIdx         As Int16
            Dim CategoryName            As String
            dim prevCategory            as String  = String.Empty ' added
            dim index                   as integer = 0
            Dim CategoriesIndexes       As New System.Collections.ArrayList()
     
            For i As Integer = 0 To FileCount
                Filenames(i) = TheContents(i).Name
                CategoryNameIdx = InStr(TheContents(i).Name, "-") - 1
                CategoryName = TheContents(i).Name.Substring(0, CategoryNameIdx)
     
                if CategoryName <> prevCategory then
                    Categories.Insert(i, CategoryName)
                    prevCategory = CategoryName
     
                    Dim Category As New Category
                    Category.Index = index
                    Category.Name = CategoryName
                    CategoriesIndexes.Add( Category )
                    index = index + 1
                end if
     
            Next
     
            refCategories = CategoriesIndexes
            refFilenames  = Filenames
     
        End Sub
     
        private Class ExtData
            private _ext as string
            private _icon as string
            private _type as string
     
            public sub new (ext as string, icon as string, type as string)
                _ext = ext
                if icon = String.Empty then
                    icon = ext
                 else
                    icon = icon
                end if
                if type = String.Empty then
                    type = ext + " file type"
                else
                    _type = type
                end if
            end sub
            public readonly property ext as string
                get
                    return _ext
                end get
            end property
            public readonly property icon as string
                get
                    return _icon
                end get
            end property
            public readonly property type as string
                get
                    return _type
                end get
            end property
        end class
        private const ExtensionInfo() as string = { _
            new ExtData("asp", String.Empty,"Active Server Page"), _
            new ExtData("aspx", "asp", "ASP.Net Web Forms Page"), _
            new ExtData("asx", "unknown", "Windows Media File"), _
            new ExtData("avi", "unknown", "Video File"), _
            new ExtData("bmp", String.Empty,"Bitmapped Image"), _
            new ExtData("config", "cfg",String.Empty, _
            new ExtData("css", String.Empty,String.Empty, _
            new ExtData("doc", String.Empty,"Microsoft Word Document"), _
            new ExtData("dv", "unknown", "Video File"), _
            new ExtData("exe", String.Empty,"Executable"), _
            new ExtData("fig", String.Empty,String.Empty, _
            new ExtData("fla", String.Empty,String.Empty, _
            new ExtData("gif", String.Empty,"GIF Image"), _
            new ExtData("gz", "rar","Compressed Archive"), _
            new ExtData("htm", "html", "Hypertext Markup File"), _
            new ExtData("html", "html", "Hypertext Markup File"), _
            new ExtData("jfif", "unknown", "JPEG Image"), _
            new ExtData("jpeg", "unknown", "JPEG Image"), _
            new ExtData("jpg", String.Empty,"JPEG Image"), _
            new ExtData("mid", "wmf", String.Empty, _
            new ExtData("mp3", "wmf","MP3 Audio File"), _
            new ExtData("mpeg", "wmf","Video File"), _
            new ExtData("mpg", "wmf","Video File"), _
            new ExtData("pdf", "unknown", "Adobe Acrobat Document"), _
            new ExtData("peg", String.Empty,String.Empty, _
            new ExtData("png", "gif",  "PNG Image"), _
            new ExtData("psd", String.Empty,"Adobe Photoshop Document"), _
            new ExtData("rar", String.Empty,"Compressed Archive"), _
            new ExtData("rtf", "unknown", "Rich Text"), _
            new ExtData("swf", String.Empty,"Macromedia Flash Animation"), _
            new ExtData("tml", "html", "Hypertext Markup File"), _
            new ExtData("txt", "text", "Plain Text"), _
            new ExtData("wav", "wmf", String.Empty, _
            new ExtData("wma", "wmf","Windows Media File"), _
            new ExtData("wmv", "wmf","Windows Media File"), _
            new ExtData("xls", String.Empty,"Microsoft Excel Workbook"), _
            new ExtData("zip", String.Empty,"Compressed Archive") _
        }
     
        Public Shared Function GetIconForFilename(ByVal strPath As String) As String
            dim strIcon as string = "unknown"
            Dim strExt As String
            Dim strIcon As String
            If InStr(1, strPath.ToString, ".") <> 0 Then
                strExt = Mid(strPath, InStrRev(strPath, ".") + 1).ToLower.Replace(LCase(strExt), ".", "")
                'strExt = Replace(LCase(strExt), ".", "")
            End If
     
            for each e as ExtData in ExtensionInfo
                if e.ext = strExt then
                    strIcon = e.Icon
                    exit for
                end if
            next
            Return "http://www.w3bdevil.com/fso/" & strIcon & ".gif"
        End Function
     
        Public Shared Function ReturnType(ByVal strExt As String) As String
            for each e as ExtData in ExtensionInfo
                if e.ext = strExt then
                    return e.type
                end if
            next
            Return strExt & " file"
        End Function
     
     

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.