[英]How efficiently sort a list by groups?
I need to group a given sort list by some given "blocks" or "groups" of elements.我需要按一些给定的“块”或“组”元素对给定的排序列表进行分组。 For example:
例如:
Given a list:给出一个列表:
[A, B, C, D, E, F, G, H, I, J]
And groups和团体
[A, C, D]
[F, E]
[J, H, I]
the result should be结果应该是
[A, C, D, B, F, E, G, J, H, I]
The blocks of elements can not be mixed with non-group elements.元素块不能与非组元素混合。 The blocks should have the same order.
块应该具有相同的顺序。 The other elements of the list should mantain their order.
列表的其他元素应该保持它们的顺序。
I have already found a solution.我已经找到了解决方案。 But it's not the most efficient code as you will see.
但这并不是您将看到的最有效的代码。
I'm using java 6 also...我也在使用 java 6 ......
public static List<CategoryProduct> sortProductsByBlocks(List<CategoryProduct> products, CategoryBlocks categoryBlocks) {
if (!validateCategoryBlocks(categoryBlocks)) {
return products;
}
Map<String, BlockView> mapProductByBlock = mapBlocksByPartnumber(categoryBlocks);
Map<String, BlockView> mapFirstProductByBlock = mapFirstProductByBlock(categoryBlocks);
Map<Integer, Block> blocksById = blocksById(categoryBlocks);
List<CategoryProduct> sortedProduct = Lists.newArrayList();
Map<String, CategoryProduct> productsMapByPartNumber = ProductHelper.getProductsMapByPartNumber(products);
List<CategoryProduct> processedProducts = Lists.newArrayList();
int j = 0;
for (int i = 0; i < products.size(); i++) {
CategoryProduct product = products.get(i);
if (blocksById.isEmpty() && !processedProducts.contains(product)) {
sortedProduct.add(j++, product);
processedProducts.add(product);
}
if (!processedProducts.contains(product) && (mapFirstProductByBlock.get(product.getPartNumber()) != null
|| mapProductByBlock.get(product.getPartNumber()) == null)) {
BlockView blockView = mapProductByBlock.get(product.getPartNumber());
if (blockView != null) {
Block block = blocksById.get(blockView.getBlockId());
if (block == null) {
sortedProduct.add(j++, product);
continue;
}
for (BlockProduct blockProduct : block.getProducts()) {
CategoryProduct categoryProduct = productsMapByPartNumber.get(blockProduct.getPartnumber());
sortedProduct.add(j++, categoryProduct);
processedProducts.add(categoryProduct);
}
blocksById.remove(blockView.getBlockId());
} else {
sortedProduct.add(j++, product);
processedProducts.add(product);
}
}
}
return sortedProduct;
}
Any advice to improve and make it faster will be welcome.欢迎任何改进和使其更快的建议。
(edit with the improved code) (使用改进的代码进行编辑)
public static List<CategoryProduct> sortProductsByBlocks2(List<CategoryProduct> products,
CategoryBlocks categoryBlocks) {
if (!validateCategoryBlocks(categoryBlocks)) {
return products;
}
Map<String, Integer> blocksIdByFirstPartnumber = Maps.newHashMap();
List<String> partnumbersInBlocks = Lists.newArrayList();
for (int k = 0; k < categoryBlocks.getBlocks().size(); k++) {
Block block = categoryBlocks.getBlocks().get(k);
if (block != null && block.getProducts() != null) {
for (int i = 0; i < block.getProducts().size(); i++) {
BlockProduct blockProduct = block.getProducts().get(i);
if (i == 0) {
blocksIdByFirstPartnumber.put(blockProduct.getPartnumber(), k);
} else {
partnumbersInBlocks.add(blockProduct.getPartnumber());
}
}
}
}
CategoryProduct[] result = new CategoryProduct[products.size()];
Map<String, Integer> productsIndex = Maps.newHashMap();
Map<String, CategoryProduct> categoryProductByPartnumber = Maps.newHashMap();
int indexResult = 0;
for (CategoryProduct categoryProduct : products) {
String partNumber = categoryProduct.getPartNumber();
if (!partnumbersInBlocks.contains(partNumber)) {
if (blocksIdByFirstPartnumber.get(partNumber) != null) {
Block categoryProductBlock = categoryBlocks.getBlocks()
.get(blocksIdByFirstPartnumber.get(partNumber));
result[indexResult] = categoryProduct;
indexResult++;
for (int i = 1; i < categoryProductBlock.getProducts().size(); i++) {
BlockProduct blockProduct = categoryProductBlock.getProducts().get(i);
if (categoryProductByPartnumber.get(blockProduct.getPartnumber()) != null) {
result[indexResult] = categoryProductByPartnumber.get(blockProduct.getPartnumber());
} else {
productsIndex.put(blockProduct.getPartnumber(), indexResult);
result[indexResult] = null;
}
indexResult++;
}
} else {
result[indexResult] = categoryProduct;
indexResult++;
}
} else {
if (productsIndex.get(partNumber) != null) {
result[productsIndex.get(partNumber)] = categoryProduct;
} else {
categoryProductByPartnumber.put(partNumber, categoryProduct);
}
}
}
return Lists.newArrayList(Arrays.asList(result));
}
Performance:表现:
Elements New algorithm Old algorithm元素 新算法 旧算法
1200 0.002s 0.129s 1200 0.002s 0.129s
12000 0.021s 14.673s 12000 0.021s 14.673s
Form the code you submitted, I cannot figure out how your algorithm is fully working.从您提交的代码中,我无法弄清楚您的算法是如何完全工作的。
I can write another algorithm that will do the task.我可以编写另一种算法来完成这项任务。
Mark the first element for each group标记每组的第一个元素
[A,C,D] -> A
Remove from list(to_be_sorted)
all elements from groups that are not marked从
list(to_be_sorted)
删除未标记的组中的所有元素
[A,C,D] -> remove [C,D]
perform sort on list对列表执行排序
result ([A,B,F,G,J])
place removed element based on Mark根据 Mark 放置移除的元素
Initial Sorted List [A,B,F,G,J] A->add [C,D] List is [A,C,D,B,F,G,J] B->as it is F->add [E] List is [A,C,D,B,F,E,G,J] G->as it is J->add [H,I] Final Sorted List [A,C,D,B,F,E,G,J,H,I]
Time complexity is the same as sorting algorithm时间复杂度与排序算法相同
By your definition it isn't entirely clear what the conditions are to merge the results from your given list and 'groups' ( arrays ).根据您的定义,合并给定列表和“组”(数组)中的结果的条件并不完全清楚。 However, here is a solution based on your requirements using the assertion
但是,这是使用断言基于您的要求的解决方案
"You want the first element of the list not contained in any of the groups inserted between the groups... "
“您希望列表的第一个元素不包含在任何插入组之间的组中......”
public class MergeArrays {
private static final List<String> FIRST = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J"));
private static final List<String> SECOND = new ArrayList<>(Arrays.asList("A", "C", "D"));
private static final List<String> THIRD = new ArrayList<>(Arrays.asList("F", "E"));
private static final List<String> FOURTH = new ArrayList<>(Arrays.asList("J", "H", "I"));
public static List<String> merge(List<String> source, List<String>... lists) {
List<String> result = new ArrayList<>();
for (List<String> list : lists) {
for (String value : list) {
source.remove(value);
}
}
for (List<String> list : lists) {
String value = null;
if (source.size() > 0) {
value = source.get(0);
source.remove(0);
}
result.addAll(merge(value, list));
}
return result;
}
public static List<String> merge(String value, List<String> list) {
List<String> result = new ArrayList<>(list);
if (value != null) {
result.add(value);
}
return result;
}
public static void main(String[] args) {
List<String> result = merge(FIRST, SECOND, THIRD, FOURTH);
System.out.println(result);
}
}
//Results //结果
[A, C, D, B, F, E, G, J, H, I]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.