我有一个产品列表:
public IList<JObject> WhenListProducts()
{
return new List<JObject>
{
JObject.Parse("{ \"gtin\": 1, \"categoryId\": \"cameras\", \"brand\": \"Sony\", \"colour\": \"Blacks\", \"size\": \"Small\", \"quality\": \"Medium\", \"price\": 109.99, \"importance\": 50 }"),
JObject.Parse("{ \"gtin\": 2, \"categoryId\": \"cameras\", \"brand\": \"Canon\", \"colour\": \"Blacks\", \"size\": \"Large\", \"quality\": \"High\", \"price\": 129.99, \"importance\": 125 }"),
JObject.Parse("{ \"gtin\": 3, \"categoryId\": \"cameras\", \"brand\": \"Canon\", \"colour\": \"Blacks\", \"size\": \"Small\", \"quality\": \"Medium\", \"price\": 99.99, \"importance\": 75 }"),
JObject.Parse("{ \"gtin\": 4, \"categoryId\": \"cameras\", \"brand\": \"Nikon\", \"colour\": \"Silvers\", \"size\": \"Large\", \"quality\": \"High\", \"price\": 159.99, \"importance\": 113 }"),
JObject.Parse("{ \"gtin\": 5, \"categoryId\": \"cameras\", \"brand\": \"Sony\", \"colour\": \"Silvers\", \"size\": \"Small\", \"quality\": \"High\", \"price\": 179.99, \"importance\": 150 }"),
JObject.Parse("{ \"gtin\": 6, \"categoryId\": \"cameras\", \"brand\": \"Canon\", \"colour\": \"Silvers\", \"size\": \"Large\", \"quality\": \"Low\", \"price\": 116.99, \"importance\": 25 }"),
JObject.Parse("{ \"gtin\": 7, \"categoryId\": \"cameras\", \"brand\": \"Sony\", \"colour\": \"Blacks\", \"size\": \"Small\", \"quality\": \"High\", \"price\": 189.99, \"importance\": 150 }"),
JObject.Parse("{ \"gtin\": 8, \"categoryId\": \"cameras\", \"brand\": \"Nikon\", \"colour\": \"Blacks\", \"size\": \"Large\", \"quality\": \"Medium\", \"price\": 129.99, \"importance\": 13 }"),
JObject.Parse("{ \"gtin\": 9, \"categoryId\": \"cameras\", \"brand\": \"Canon\", \"colour\": \"Reds\", \"size\": \"Small\", \"quality\": \"High\", \"price\": 179.99, \"importance\": 175 }"),
JObject.Parse("{ \"gtin\": 10, \"categoryId\": \"cameras\", \"brand\": \"Nikon\", \"colour\": \"Silvers\", \"size\": \"Small\", \"quality\": \"High\", \"price\": 185.99, \"importance\": 163 }"),
JObject.Parse("{ \"gtin\": 11, \"categoryId\": \"cameras\", \"brand\": \"Nikon\", \"colour\": \"Blacks\", \"size\": \"Large\", \"quality\": \"High\", \"price\": 159.99, \"importance\": 113 }"),
JObject.Parse("{ \"gtin\": 12, \"categoryId\": \"cameras\", \"brand\": \"Nikon\", \"colour\": \"Silvers\", \"size\": \"Small\", \"quality\": \"Low\", \"price\": 69.99, \"importance\": 63 }"),
};
}
我按重要性排序。 在某些情况下,它们具有相同的重要性。在这种情况下,有2个产品的重要性为150。 因此,我想确保在该部分中它们的顺序正确,因此我创建了一些排序,应重新排列产品。
public List<Sortation> WhenListSortations()
{
return new List<Sortation>
{
new Sortation
{
Field = "colour",
Expression = "Blacks",
Order = 0
},
new Sortation
{
Field = "colour",
Expression = "Greys",
Order = 1
},
new Sortation
{
Field = "colour",
Expression = "Silvers",
Order = 2
},
new Sortation
{
Field = "colour",
Expression = "Whites",
Order = 3
},
new Sortation
{
Field = "colour",
Expression = "Blues",
Order = 4
},
new Sortation
{
Field = "colour",
Expression = "Pinks",
Order = 5
},
new Sortation
{
Field = "colour",
Expression = "Yellows",
Order = 6
},
new Sortation
{
Field = "price",
Expression = "0",
Order = 7
},
new Sortation
{
Field = "latestModel",
Expression = "Yes",
Order = 8
}
};
}
我创建了一些测试:
[Test]
public async Task ShouldHaveHighestImportanceTopAndLowestBottom()
{
// Assemble
var services = SortContext.GivenServices();
var sortProvider = services.WhenCreateSortProvider();
var products = services.WhenListProducts();
var sortations = services.WhenListSortations();
services.MockSortationProvider.Setup(x => x.ListAsync("cameras")).ReturnsAsync(sortations);
// Act
var sortedProducts = await sortProvider.SortAsync(products);
// Assert
sortedProducts.First()["importance"].ToString().Should().Be("175");
sortedProducts.Last()["importance"].ToString().Should().Be("13");
}
[Test]
public async Task ShouldSortEqualImportanceBySortation()
{
// Assemble
var services = SortContext.GivenServices();
var sortProvider = services.WhenCreateSortProvider();
var products = services.WhenListProducts();
var sortations = services.WhenListSortations();
services.MockSortationProvider.Setup(x => x.ListAsync("cameras")).ReturnsAsync(sortations);
// Act
var sortedProducts = await sortProvider.SortAsync(products);
// Assert
sortedProducts[0]["importance"].ToString().Should().Be("175");
sortedProducts[1]["importance"].ToString().Should().Be("163");
sortedProducts[2]["importance"].ToString().Should().Be("150");
sortedProducts[3]["importance"].ToString().Should().Be("150");
sortedProducts[4]["importance"].ToString().Should().Be("125");
sortedProducts[2]["colour"].ToString().Should().Be("Blacks");
sortedProducts[3]["colour"].ToString().Should().Be("Silvers");
}
我解决这个问题的方法如下:
public async Task<IList<JObject>> SortAsync(IList<JObject> products)
{
_productListValidator.Validate(products, "gtin", "categoryId", "importance");
var categoryId = products[0]["categoryId"]?.ToString();
var sortations = await _sortationProvider.ListAsync(categoryId);
if (sortations == null || sortations.Count == 0) return products;
var orderedSortations = sortations.OrderBy(m => m.Order).ToList();
var orderedProducts = products.OrderByDescending(m => Convert.ToInt32(m["importance"].ToString())).ToList();
var groups = orderedProducts.GroupBy(m => m["importance"].ToString());
var sortedProducts = orderedProducts.OrderBy(a => 1);
foreach(var group in groups)
{
if (group.Count() == 1) continue;
// TODO: re-order the grouped products by sortation
}
var t = sortedProducts.ToList();
return t;
}
按现状显示,使用该代码运行我的测试将通过第一个测试,但不会通过最后一个测试。因此,我添加了我的代码,用于对150个2个产品进行排序。看起来像这样:
var groupProducts = group.ToList().OrderBy(a => 1);
var result = orderedSortations.Aggregate(groupProducts,
(current, sortation) =>
{
if (sortation.Field.Equals("price", StringComparison.OrdinalIgnoreCase))
return sortation.Expression.Equals("0") ?
current.ThenBy(m => Convert.ToDecimal(m["price"].ToString())) :
current.ThenByDescending(m => Convert.ToDecimal(m["price"].ToString()));
return current.ThenByDescending(m => m.ContainsKey(sortation.Field) && m[sortation.Field].ToString().Equals(sortation.Expression));
}).ToList();
var gtins = result.Select(m => m["gtin"].ToString()).ToList();
sortedProducts = sortedProducts.ThenBy(m => gtins.IndexOf(m["gtin"].ToString()));
因此完整的方法如下:
public async Task<IList<JObject>> SortAsync(IList<JObject> products)
{
_productListValidator.Validate(products, "gtin", "categoryId", "importance");
var categoryId = products[0]["categoryId"]?.ToString();
var sortations = await _sortationProvider.ListAsync(categoryId);
if (sortations == null || sortations.Count == 0) return products;
var orderedSortations = sortations.OrderBy(m => m.Order).ToList();
var orderedProducts = products.OrderByDescending(m => Convert.ToInt32(m["importance"].ToString())).ToList();
var groups = orderedProducts.GroupBy(m => m["importance"].ToString());
var sortedProducts = orderedProducts.OrderBy(a => 1);
foreach(var group in groups)
{
if (group.Count() == 1) continue;
var groupProducts = group.ToList().OrderBy(a => 1);
var result = orderedSortations.Aggregate(groupProducts,
(current, sortation) =>
{
if (sortation.Field.Equals("price", StringComparison.OrdinalIgnoreCase))
return sortation.Expression.Equals("0") ?
current.ThenBy(m => Convert.ToDecimal(m["price"].ToString())) :
current.ThenByDescending(m => Convert.ToDecimal(m["price"].ToString()));
return current.ThenByDescending(m => m.ContainsKey(sortation.Field) && m[sortation.Field].ToString().Equals(sortation.Expression));
}).ToList();
var gtins = result.Select(m => m["gtin"].ToString()).ToList();
sortedProducts = sortedProducts.ThenBy(m => gtins.IndexOf(m["gtin"].ToString()));
}
var t = sortedProducts.ToList();
return t;
}
问题是,即使它确实正确订购了2种产品,也将它们放在我的列表的底部:( 有人可以帮我排序当前位置吗?
您应该能够获取并运行代码,如果您需要更多信息,请告诉我。
答案 0 :(得分:0)
我想我做到了。我的方法还可以,我应该在排序后按重要性进行排序:
return sortedProducts.OrderByDescending(m => Convert.ToInt32(m["importance"].ToString())).ToList();
我删除了该调用的第一个实例,并且效果很好。