最近我问了这个问题:
Find Common Values in several arrays, or lists VB.NET
我正在尝试在库存数据库的发票处建立一个智能库存拣货/发货地点系统。可以从多个位置进行调度,基本上我想进行有效的调度,因此如果可以从一个位置调度所有购买的项目,则将它们分组并分派,但如果没有,则将其分组,然后分配其余的从最高库存水平可用的地方。
在度假期间考虑了一点,我认为我不能那样接近它。
两个原因
因此,我现在不列出合适的库存地点,而是列出每个地点可用的库存数量。
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中挑选所有四个商品,只提供购买每个商品中的一个。假设客户购买了第3项中的2项。然后选择必须来自位置2.当然,所有其他方案都可以根据购买的商品数量,购买的商品数量以及购买的库存数量来呈现是要选择。
我开始只是从具有最高可用库存的位置进行挑选,但是当从多个地点选择库存时没有任何意义,因为我们最终得到了多个不需要的调度位置。
如何分析这些可变长度的字符串/数组以确定最智能的分派方式。
我可以用我的人脑很好地从库存表中解决它,但是看不到如何编程VB.NET来做到这一点!
请帮助VB示例,虽然我很感谢原始问题的帮助,但我没有说明,但我不能使用Linq,因为我在.NET 2.0框架上。
答案 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