【问题标题】:Convert List of pairs into list of grouped pairs将对列表转换为分组对列表
【发布时间】:2018-01-12 11:46:15
【问题描述】:

我无法为这个问题找到一个好的线程名称:C 我有具有两个长值字段的对象列表:

class ObjectFromDb {
    Long dbUserId;
    Long apiUserId;
}

例如。它可能看起来像这样:

List<ObjectFromDb> dbList = {
    {1, 1},
    {2, 2},
    {2, 3},
    {3, 4},
    {4, 4},
    {5, 4},
    {6, 5}
}

目标是将此列表分组为关系。可能性是: 一对一,一对多,多对一。不允许多对多。

我的最终目标:

class FinalObject {
    List<Long> dbIds;
    List<Long> apiIds;
}

所以结果列表应该是:

List<FinalObject> finalList = {
    { {1}    , {1}   },
    { {2}    , {2,3} },
    { {3,4,5}, {4}   },
    { {6}    , {5}   }
}

这是我的问题。有什么算法可以解决这样的问题吗?或者,如果有人知道如何处理它?我试图解决它,但它以十亿个 if 和 for 循环结束,所以我重新开始并以另外十亿个循环结束..

【问题讨论】:

  • 如何解决冲突?例如,如果您添加对 {3, 2} 它可以添加为 {3, {2, 4}} 和 {{2, 3}, 2},它将适合两个位置。
  • 如果某个数字在左侧,则无法再次添加。与正确的多头相同
  • 所以你可能会在分组过程中失去一些关系?
  • 如果它像在finalList中,我将添加{3,2}这个值应该被删除,因为3已经有一个关系({3,4,5 }-{4} 和 2 已经有关系({2}, {2,3})
  • 就像 SaiBot 说的:你根本无法从 relation({3,4,5},{4}) 重构 {3,2}。您只能从relation({2}, {2,3}) 重构{2,3},但不能重构{3,2}

标签: java algorithm list stream converter


【解决方案1】:

我不确定您的关系算法是否涵盖所有可能性,但这里是提供您想要的输出的代码。

我解释了它的作用以及它如何与 cmets 一起工作。

  // First it is gonna group dbUserIds and apiUserIds between each other. To keep this data, we are gonna use hashMaps
        Map<Long, List<Long>> dbUserIdGroup = new HashMap<Long, List<Long>>();
        Map<Long, List<Long>> apiUserIdGroup = new HashMap<Long, List<Long>>();

        // To demonstrate the test data given by you
        List<ObjectFromDb> dbList = new ArrayList<ObjectFromDb>();
        dbList.add(new ObjectFromDb(1L, 1L));
        dbList.add(new ObjectFromDb(2L, 2L));
        dbList.add(new ObjectFromDb(2L, 3L));
        dbList.add(new ObjectFromDb(3L, 4L));
        dbList.add(new ObjectFromDb(4L, 4L));
        dbList.add(new ObjectFromDb(5L, 4L));
        dbList.add(new ObjectFromDb(6L, 5L));

        // Iterating the given ObjectFromDb instances to group them 
        for (ObjectFromDb objectFromDb : dbList) {

            // Grouping according to dbUserId
            if (dbUserIdGroup.get(objectFromDb.getDbUserId()) == null) {
                List<Long> group = new ArrayList<Long>();
                group.add(objectFromDb.getApiUserId());
                dbUserIdGroup.put(objectFromDb.getDbUserId(), group);
            } else {
                dbUserIdGroup.get(objectFromDb.getDbUserId()).add(objectFromDb.getApiUserId());
            }

            // Grouping according to apiUserId
            if (apiUserIdGroup.get(objectFromDb.getApiUserId()) == null) {
                List<Long> group = new ArrayList<Long>();
                group.add(objectFromDb.getDbUserId());
                apiUserIdGroup.put(objectFromDb.getApiUserId(), group);
            } else {
                apiUserIdGroup.get(objectFromDb.getApiUserId()).add(objectFromDb.getDbUserId());
            }
        }

        // Up to now, we have two grouped hashmaps 
        // dbUserIdGroup ->  {"1":[1],"2":[2,3],"3":[4],"4":[4],"5":[4],"6":[5]} // note that the key of this hashtable is dbUserId
        // apiUserIdGroup ->  {"1":[1],"2":[2],"3":[2],"4":[3,4,5],"5":[6]} //  note that the key of this hashtable is apiUserId
        Set<Long> dbUserIds = dbUserIdGroup.keySet(); // to iterate dbUserId group we get its keys (dbUserIds)

        Set<List<Long>> existanceCheck = new HashSet<>(); // to avoid duplicated data

        List<FinalObject> result = new ArrayList<FinalObject>(); // to keep the result
        for (Long dbUserId : dbUserIds) {
            FinalObject fObject = null;
            List<Long> dbApiIdList = dbUserIdGroup.get(dbUserId);

            if (dbApiIdList.size() == 1) { // if the value is the list with single element
                List<Long> groupedDbUserId = apiUserIdGroup.get(dbApiIdList.get(0));
                if (!existanceCheck.contains(groupedDbUserId)) {
                    fObject = new FinalObject(groupedDbUserId, dbApiIdList);
                    existanceCheck.add(groupedDbUserId);
                    result.add(fObject);
                }
            } else { // if the value is the list with multiple elements
                List<Long> dbUserIdList = new ArrayList<Long>();
                dbUserIdList.add(dbUserId);
                fObject = new FinalObject(dbUserIdList, dbApiIdList);
                result.add(fObject);
            }

        }

        // Now you have a List<FinalObject> result array just like you want.

【讨论】:

    【解决方案2】:

    以下是解决方案的想法:

    步骤1(多对一关系):根据dbUserIDdbList进行排序,将apiUserIds与相同的dbUserID合并,并从dbList中删除对应关系(在代码中我新建了一个列表名为updatedDbList1)。

    第2步(一对多关系):根据apiUserIddbList进行排序,将dbUserIDs与相同的apiUserIds组合并从dbList中删除对应关系(在代码中我新建了一个列表名为updatedDbList2)。

    第 3 步(一对一关系):将剩余的关系添加到最终结果中。

    这就是我想出的,不过我相信只要多考虑一下就可以做得更干净。

    List<FinalObject> finalList = new ArrayList<>();
    
    //Step 1: Extract many to one relations
    //assuming dbList is sorted according to dbUserId, if not perform dbList.sort() with custom comparator
    List<ObjectFromDb> updatedDbList1 = new ArrayList<>();
    ArrayList<Long> apiUserIDs = new ArrayList<Long>();
    Long currentdbUserID = -1L;
    for(int i=0; i < dbList.size(); i++) {
        if(dbList.get(i).dbUserId != currentdbUserID) {
            if(apiUserIDs.size() >= 2) {
                ArrayList<Long> dbUserIDs = new ArrayList<Long>();
                dbUserIDs.add(currentdbUserID);
                finalList.add(new FinalObject(dbUserIDs, apiUserIDs));
            }
            if(i==dbList.size()-1 || dbList.get(i).dbUserId != dbList.get(i+1).dbUserId){
                updatedDbList1.add(dbList.get(i));
            }
            currentdbUserID = dbList.get(i).dbUserId;
            apiUserIDs = new ArrayList<Long>();
        }
        apiUserIDs.add(dbList.get(i).apiUserId);
    }
    
    //Step 2: Extract one to many relations
    //assuming dbList is sorted according to apiUserId, if not perform dbList.sort() with custom comparator
    List<ObjectFromDb> updatedDbList2 = new ArrayList<>();
    ArrayList<Long> dbUserIDs = new ArrayList<Long>();
    Long currentApiUserID = -1L;
    for(int i=0; i < updatedDbList1.size(); i++) {
        if(updatedDbList1.get(i).apiUserId != currentApiUserID) {
            if(dbUserIDs.size() >= 2) {
                apiUserIDs = new ArrayList<Long>();
                apiUserIDs.add(currentApiUserID);
                finalList.add(new FinalObject(dbUserIDs, apiUserIDs));
            }
            if(i==updatedDbList1.size()-1 || updatedDbList1.get(i).apiUserId != updatedDbList1.get(i+1).apiUserId){
                updatedDbList2.add(updatedDbList1.get(i));
            }
            currentApiUserID = updatedDbList1.get(i).apiUserId;
            dbUserIDs = new ArrayList<Long>();
        }
        dbUserIDs.add(updatedDbList1.get(i).dbUserId);
    }
    
    //Step 3: Extract one to one relations
    for(int i=0; i < updatedDbList2.size(); i++) {
        dbUserIDs = new ArrayList<Long>();
        dbUserIDs.add(updatedDbList2.get(i).dbUserId);
        apiUserIDs = new ArrayList<Long>();
        apiUserIDs.add(updatedDbList2.get(i).apiUserId);
        finalList.add(new FinalObject(dbUserIDs, apiUserIDs));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-02
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-03
      • 1970-01-01
      相关资源
      最近更新 更多