智能地将数组与.NET 2.0 VB进行比较

时间:2011-12-28 18:21:42

标签: .net vb.net arrays .net-2.0

最近我问了这个问题:

Find Common Values in several arrays, or lists VB.NET

我正在尝试在库存数据库的发票处建立一个智能库存拣货/发货地点系统。可以从多个位置进行调度,基本上我想进行有效的调度,因此如果可以从一个位置调度所有购买的项目,则将它们分组并分派,但如果没有,则将其分组,然后分配其余的从最高库存水平可用的地方。

在度假期间考虑了一点,我认为我不能那样接近它。

两个原因

  1. 由于位置数量必须是可变的,因此该系统是可扩展的。
  2. 因为项目数量也可以扩展
  3. 因此,我现在不列出合适的库存地点,而是列出每个地点可用的库存数量。

     Items       Locations
    _________|__1___|___2__|__3__| - this is location IDs
    Item 1   |  3   ,   4  ,  1    - this is the qty of stock available
    Item 2   |  2   ,   4  ,  0    
    Item 3   |  1   ,   3  ,  1    
    Item 4   |  6   ,   1  ,  3    
    

    我可以将其转换为可用于拆分和创建数组的字符串

     stockDetails = "3,4,1|2,4,0|1,3,1|6,1,3"
    

    此处,逗号分隔值是每个库存位置的可用库存数量,而管道将各个项目分开,因此上表将转换为上面的字符串。

    我并不热衷于多维数组,也不知道如何在不知道有多少库存位置的情况下创建一个。

    我们可以安全地假设

    1. 库存数量的正确顺序与库存位置ID相关联。
    2. 每个管道分隔的逗号分隔值系列将具有相同数量的逗号分隔值。
    3. 我无法弄清楚如何确定选择位置!

      在上面的示例中,实际上可以从库存位置1中挑选所有四个商品,只提供购买每个商品中的一个。假设客户购买了第3项中的2项。然后选择必须来自位置2.当然,所有其他方案都可以根据购买的商品数量,购买的商品数量以及购买的库存数量来呈现是要选择。

      我开始只是从具有最高可用库存的位置进行挑选,但是当从多个地点选择库存时没有任何意义,因为我们最终得到了多个不需要的调度位置。

      如何分析这些可变长度的字符串/数组以确定最智能的分派方式。

      我可以用我的人脑很好地从库存表中解决它,但是看不到如何编程VB.NET来做到这一点!

      请帮助VB示例,虽然我很感谢原始问题的帮助,但我没有说明,但我不能使用Linq,因为我在.NET 2.0框架上。

1 个答案:

答案 0 :(得分:2)

如果这是我的申请,我会创建一个小类,对于每个位置,将保存每个请求产品的可用数量列表。

检索数据后,我会为每个至少有一个产品有库存的位置创建这些位置类的集合。

然后,我会有一个方法,提供一个权重,以指示可以从该位置完成的产品百分比。如果已知的话,我也可能有一种方法来指示从该位置到交付地点的距离。

位置类将使用产品百分比和距离作为比较指标来实现IComparable,以便可以在集合中对项目进行排序。

要确定订单的履行地点,我会执行以下操作:

1)对位置列表进行排序,然后在列表中选择第一个位置。如果位置已知,则这也是最靠近交货地点的位置。

2)如果在步骤1中选择的位置不满足订单的100%,则循环查看位置列表并删除所选位置满足的产品。如果给定位置为0%,请将其从位置集合中删除。

3)如果尚未挑选所有产品且列表中仍有位置,请从步骤1重新开始。

希望这有助于您走上正确的轨道。

<强>更新

这是让你入门的东西。

这是位置类的开始

Public Class LocationQuantities
    Implements IComparable

    Public Sub New()
        m_cProductQuantities = New Generic.Dictionary(Of Integer, Decimal)
    End Sub

    Private m_wLocationId As Integer

    Public Property LocationId As Integer
        Get
            Return m_wLocationId
        End Get
        Set(value As Integer)
            m_wLocationId = value
        End Set
    End Property

    Private m_cProductQuantities As Generic.Dictionary(Of Integer, Decimal)
    ''' <summary>
    ''' A collection of quantities for each product. The key to the collection is the product id
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property ProductQuantities As Generic.Dictionary(Of Integer, Decimal)
        Get
            Return m_cProductQuantities
        End Get
    End Property

    Private m_dWeight As Double
    ''' <summary>
    ''' This contains the weight of products for this location as set in CalculateWeight
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property Weight As Double
        Get
            Return m_dWeight
        End Get
    End Property

    ''' <summary>
    ''' This method sets the weight for the specified list of product ids
    ''' </summary>
    ''' <param name="cProductIds"></param>
    ''' <remarks></remarks>
    Public Sub CalculateWeight(cProductIds As Generic.List(Of Integer))

        Dim wAvailableProducts As Integer

        ' Cycle through the list of available products
        For Each wProductId As Integer In cProductIds
            ' If our list of products contains the specified product and the product quantity is not 0
            If Me.ProductQuantities.ContainsKey(wProductId) AndAlso Me.ProductQuantities(wProductId) <> 0 Then
                ' Increase the count
                wAvailableProducts += 1
            End If
        Next

        ' Finally calculate the weight as the percentage of available products 
        If cProductIds.Count <> 0 Then
            m_dWeight = wAvailableProducts / cProductIds.Count
        Else
            m_dWeight = 0
        End If
    End Sub

    ''' <summary>
    ''' This method is used to compare one location to the next
    ''' </summary>
    ''' <param name="obj"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CompareTo(obj As Object) As Integer Implements System.IComparable.CompareTo

        With DirectCast(obj, LocationQuantities)
            Return .Weight.CompareTo(Me.Weight)
        End With
    End Function

    ''' <summary>
    ''' This method is used to add a quantity for the specified productid
    ''' </summary>
    ''' <param name="wProductId"></param>
    ''' <param name="dQuantity"></param>
    ''' <remarks></remarks>
    Public Sub AddQuantityForProductId(wProductId As Integer, dQuantity As Decimal)

        ' First, see if the product id exists in the list of our product quantities
        If Me.ProductQuantities.ContainsKey(wProductId) Then
            ' It does exist, so add the new quantity to the existing value
            Me.ProductQuantities(wProductId) += dQuantity
        Else
            ' The product id does not exist, so add a new entry
            Me.ProductQuantities.Add(wProductId, dQuantity)
        End If
    End Sub
End Class

以上是执行大量工作的上述项目的集合类

''' <summary>
''' This collection contains a list if LocationQuantities keyed by LocationId
''' </summary>
''' <remarks></remarks>
Public Class LocationQuantitiesCollection
    Inherits Generic.List(Of LocationQuantities)

    ' A local dictionary used for indexing
    Private m_cDictionaries As Generic.Dictionary(Of Integer, LocationQuantities)

    Public Sub New()
        m_cDictionaries = New Generic.Dictionary(Of Integer, LocationQuantities)
    End Sub

    ''' <summary>
    ''' This method adds the product and quantity to the specified location
    ''' </summary>
    ''' <param name="wLocationId"></param>
    ''' <param name="wProductId"></param>
    ''' <param name="dQuantity"></param>
    ''' <remarks></remarks>
    Public Sub AddLocationAndQuantityForProduct(wLocationId As Integer, wProductId As Integer, dQuantity As Decimal)

        Dim oLocationQuantities As LocationQuantities

        ' First, see if the location id exists in this collection
        If m_cDictionaries.ContainsKey(wLocationId) Then
            ' It does exist, so get a local reference
            oLocationQuantities = m_cDictionaries(wLocationId)
        Else
            ' It does not exist, so add a new entry

            oLocationQuantities = New LocationQuantities
            oLocationQuantities.LocationId = wLocationId

            ' The product id does not exist, so add a new entry
            m_cDictionaries.Add(wLocationId, oLocationQuantities)

            ' Finally, add it to the underlying list
            Me.Add(oLocationQuantities)
        End If

        ' Finally, add the product and quantity to the location quantity
        oLocationQuantities.AddQuantityForProductId(wProductId, dQuantity)
    End Sub

    ''' <summary>
    ''' This method calculates the inventory for the specified products and returns a dictionary keyed by productid 
    ''' whose value is the locationid for the product
    ''' </summary>
    ''' <param name="cProductIds"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CalculateInventory(cProductIds As List(Of Integer)) As Generic.Dictionary(Of Integer, Integer)

        ' This dictionary is keyed by productid and the value is the location id that the product will be delivered from
        Dim cProductLocations As New Generic.Dictionary(Of Integer, Integer)
        ' The list of productids left to find
        Dim cProductsToFind As New Generic.Dictionary(Of Integer, Integer)

        ' Copy all requested product ids to the list of product ids to find
        For Each wProductId As Integer In cProductIds
            cProductsToFind.Add(wProductId, wProductId)
        Next

        If Me.Count <> 0 Then
            Do While cProductsToFind.Count <> 0
                Dim oLocation As LocationQuantities

                ' Calculate the weight for each of the locations
                For Each oLocation In Me
                    oLocation.CalculateWeight(cProductIds)
                Next

                ' Sort the list of locations.
                Me.Sort()

                ' Get the first location in the list, update the product locations, then remove the products from each of the locations.
                oLocation = Me.Item(0)

                ' If there are no available products, bail out of the loop
                If oLocation.Weight = 0 Then
                    Exit Do
                End If

                ' For each of the products to be found (cycle backwards because we may be removing items from the list)
                For nI As Integer = cProductsToFind.Count - 1 To 0 Step -1
                    Dim wProductId As Integer

                    ' Get the productid
                    wProductId = cProductsToFind.Keys(nI)

                    ' If this location has a quantity, record this location as the location for the product and remove the product from the list
                    ' of products to find.
                    If oLocation.ProductQuantities.ContainsKey(wProductId) AndAlso oLocation.ProductQuantities(wProductId) <> 0 Then
                        ' This code assumes that found products have been removed
                        cProductLocations.Add(wProductId, oLocation.LocationId)
                        ' Remove the product to find from the list of products to find
                        cProductsToFind.Remove(wProductId)
                    End If
                Next

                If cProductsToFind.Count <> 0 Then
                    ' If there are more products to find, remove the found products from each of the locations and process again.
                    For Each oLocation In Me
                        ' Work backwards through the list of keys since we may be removing items
                        For nI As Integer = oLocation.ProductQuantities.Keys.Count - 1 To 0 Step -1
                            Dim wProductId As Integer

                            ' Get the product id
                            wProductId = oLocation.ProductQuantities.Keys(nI)

                            ' If we no longer need to find this product id, remove it from the list of product quantities at this location
                            If Not cProductsToFind.ContainsKey(wProductId) Then
                                cProductsToFind.Remove(wProductId)
                            End If
                        Next
                    Next
                End If
            Loop
        End If

        Return cProductLocations
    End Function
End Class

最后,这是一个表单的摘录,可用于加载库存并计算给定项目的来源:

Public Class Form1

    Dim m_cLocationsAndQuantities As LocationQuantitiesCollection

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Call LoadLocationsAndQuantities()
        Call DoInventoryCalculation()
    End Sub

    ''' <summary>
    ''' Load the locations and quantities
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub LoadLocationsAndQuantities()

        m_cLocationsAndQuantities = New LocationQuantitiesCollection

        Dim wLocationId As Integer
        Dim wProductId As Integer
        Dim dQuantity As Decimal

        wLocationId = 1
        wProductId = 1
        dQuantity = 120

        m_cLocationsAndQuantities.AddLocationAndQuantityForProduct(wLocationId, wProductId, dQuantity)

        wProductId = 2
        dQuantity = 10

        m_cLocationsAndQuantities.AddLocationAndQuantityForProduct(wLocationId, wProductId, dQuantity)

        wLocationId = 2
        wProductId = 1
        dQuantity = 4

        m_cLocationsAndQuantities.AddLocationAndQuantityForProduct(wLocationId, wProductId, dQuantity)

    End Sub

    ''' <summary>
    ''' Perform the inventory calculations
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub DoInventoryCalculation()

        ' The list of productids to calculate inventory for
        Dim cProductIds As New List(Of Integer)
        ' The list of locations where each product will be obtained. The key is the productid and the value is the locationid
        Dim cLocationsAndProducts As Generic.Dictionary(Of Integer, Integer)

        Dim wProductId As Integer

        ' Calculate the inventory for productid 1
        wProductId = 1

        cProductIds.Add(wProductId)

        ' Finally, calculate the inventory
        cLocationsAndProducts = m_cLocationsAndQuantities.CalculateInventory(cProductIds)

        If cLocationsAndProducts Is Nothing OrElse cLocationsAndProducts.Count = 0 Then
            Console.WriteLine("None of the requested products could be found at any location")
        Else
            For Each wProductId In cLocationsAndProducts.Keys
                Console.WriteLine("Product ID " & wProductId & " will be delivered from Location ID " & cLocationsAndProducts(wProductId))
            Next
        End If
    End Sub

End Class

<强>更新

这是CalculateInventory方法的.Net 2.0版本:

''' <summary>
''' This method calculates the inventory for the specified products and returns a dictionary keyed by productid 
''' whose value is the locationid for the product
''' </summary>
''' <param name="cProductIds"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function CalculateInventory(cProductIds As List(Of Integer)) As Generic.Dictionary(Of Integer, Integer)

    ' This dictionary is keyed by productid and the value is the location id that the product will be delivered from
    Dim cProductLocations As New Generic.Dictionary(Of Integer, Integer)
    ' The list of productids left to find
    Dim cProductsToFind As New Generic.Dictionary(Of Integer, Integer)

    ' Copy all requested product ids to the list of product ids to find
    For Each wProductId As Integer In cProductIds
        cProductsToFind.Add(wProductId, wProductId)
    Next

    If Me.Count <> 0 Then
        Do While cProductsToFind.Count <> 0
            Dim oLocation As LocationQuantities

            ' Calculate the weight for each of the locations
            For Each oLocation In Me
                oLocation.CalculateWeight(cProductIds)
            Next

            ' Sort the list of locations.
            Me.Sort()

            ' Get the first location in the list, update the product locations, then remove the products from each of the locations.
            oLocation = Me.Item(0)

            ' If there are no available products, bail out of the loop
            If oLocation.Weight = 0 Then
                Exit Do
            End If

            Dim cKeysToRemove As New List(Of Integer)

            ' For each of the products to be found
            For Each wProductId As Integer In cProductsToFind.Keys
                ' If this location has a quantity, record this location as the location for the product and remove the product from the list
                ' of products to find.
                If oLocation.ProductQuantities.ContainsKey(wProductId) AndAlso oLocation.ProductQuantities(wProductId) <> 0 Then
                    ' This code assumes that found products have been removed
                    cProductLocations.Add(wProductId, oLocation.LocationId)
                    ' Add the productid to the list of items to be removed
                    cKeysToRemove.Add(wProductId)
                End If
            Next

            ' Now remove the productids
            For Each wProductId As Integer In cKeysToRemove
                cProductsToFind.Remove(wProductId)
            Next

            If cProductsToFind.Count <> 0 Then
                ' If there are more products to find, remove the found products from each of the locations and process again.
                For Each oLocation In Me
                    For Each wProductId As Integer In oLocation.ProductQuantities.Keys
                        ' If we no longer need to find this product id, remove it from the list of product quantities at this location
                        If Not cProductsToFind.ContainsKey(wProductId) Then
                            cProductsToFind.Remove(wProductId)
                        End If
                    Next
                Next
            End If
        Loop
    End If

    Return cProductLocations
End Function