Java 根据客户历史记录查找强链接和弱链接

Java 根据客户历史记录查找强链接和弱链接,java,Java,如果同一客户同时购买了这两种商品,则这两种商品之间存在着紧密的联系。如果两个项目与第三个项目强链接或弱链接,则它们是弱链接的 输入: {“第一:abc”,“第一:hij”,“第二:hij”,“第二:klm”,“第三:nop”,“第四:qrs”,“第四:abc”,“第一:def”,“第五:klm”,“第五:tuv”} “第一/第二/第三/第四/第五”是客户ID,“ABC,HIJ”等是项目ID。它们之间用“:”分隔 目标:找到给定项目的强链接和弱链接的数量 示例:对于“ABC”和上面的字符串输入数组

如果同一客户同时购买了这两种商品,则这两种商品之间存在着紧密的联系。如果两个项目与第三个项目强链接或弱链接,则它们是弱链接的

输入:

{“第一:abc”,“第一:hij”,“第二:hij”,“第二:klm”,“第三:nop”,“第四:qrs”,“第四:abc”,“第一:def”,“第五:klm”,“第五:tuv”}

“第一/第二/第三/第四/第五”是客户ID,“ABC,HIJ”等是项目ID。它们之间用“:”分隔

目标:找到给定项目的强链接和弱链接的数量

示例:对于“ABC”和上面的字符串输入数组,输出应为

[3,2]

强链为QRS、HIJ、DEF,弱链为KLM、TUV

方法:

public int[] getLinkCount(String itemId, String[] orderHist) {

}
我能弄明白的是:

  • 遍历阵列并为每个客户创建一个项目列表。 因此,基本上这是一个客户的HashMap。关键在于 customerID和该值将是itemID的ArrayList
  • 每人 HapMap中的项检查arraylist是否具有itemId。如果是,则返回arrayList并将这些itemId存储在strongLinks数组中
  • 从strong列表数组中删除重复项。现在你有了强者 给定itemId的链接。您可以返回计数

  • 不知道这是否是最有效的。我现在还停留在如何找到薄弱环节的问题上

    我目前没有IDE,因此我现在无法提供完整的程序,但我尝试概述一下想法。查找强链接通常与您所做的方式相同,但您最好将其与同时查找弱链接合并,以递归方式遍历hashmap,从那些项目列表包含特定元素的客户开始

    在这种情况下,客户“第一”和“第四”的项目列表中有项目“ABC”

    • 客户“first”的列表中还有项目“HIJ”和“DEF”,这些都是与“ABC”的强链接。因此,应该继续搜索那些其项目列表包含这些元素的客户。在这种情况下,客户“second”也有项目“HIJ”,除此之外,他还有“KLM”,因此“KLM”是“ABC”的薄弱环节。没有任何其他客户的商品列表中有“DEF”,因此我们到此为止。您应该继续搜索那些项目列表中包含“KLM”的客户,您将发现客户“fifth”,其项目列表中除此之外还包含“TUV”,因此这也是“ABC”的薄弱环节。没有任何其他客户的商品列表中有“TUV”,所以我们就到此为止

    • 客户“第四个”有“QRS”项,该项与“ABC”有很强的联系。没有任何其他客户在他们的商品列表中有“QRS”,所以我们就到此为止


      • 这里有一个工作版本。请参见代码中的注释:

        package strong;
        
        import java.util.Arrays;
        import java.util.Collection;
        import java.util.HashSet;
        import java.util.Set;
        import java.util.stream.Collectors;
        import java.util.stream.IntStream;
        import java.util.stream.Stream;
        
        
        public class Strong {
        
            /**
             * Are item1 and item2 strongly linked ?
             * @param item1 the first item for example "abc"
             * @param item2 the second item for example "hij"
             * @param groups example: [[nop], [tuv, klm], [qrs, abc], [abc, def, hij], 
             * [hij, klm]]
             * @return true if item1 and item2 are strongly linked 
             */
            public static boolean stronglyLinked(String item1, String item2, 
                    Collection<Set<String>> groups) {
        
                // true if groups contains a set with item1 and item2
                return groups.stream().
                        anyMatch(g-> g.contains(item1) && g.contains(item2));
            }
        
            /**
             * Are item1 and item2 weakly linked ?
             * @param item1 the first item for example "abc"
             * @param item2 the second item for example "hij"
             * @param groups example: [[nop], [tuv, klm], [qrs, abc], [abc, def, hij], 
             * [hij, klm]]
             * @return true if item1 and item2 are weakly linked 
             */
            public static boolean weaklyLinked(String item1, String item2, 
                    Collection<Set<String>> groups) {
        
                // call private implementation with bag parameter (to avoid infinite
                // recursion).
                return weaklyLinked(item1, item2, groups, new HashSet());
            }
        
        
            /**
             * Get strongly and weakly link count for the given item
             * @param itemId the item
             * @param orderHist for example: {"first:abc","first:hij", "second:hij", 
             * "second:klm", "third:nop","fourth:qrs", "fourth:abc", "first:def", 
             * "fifth:klm", "fifth:tuv"}
             * @return an array with [0] => strongly linked count, [1] => weakly linked
             * count.
             */
            public static int[] getLinkCount(String itemId, String[] orderHist) {
        
                // get groups of items bought together for example:
                // [[nop], [tuv, klm], [qrs, abc], [abc, def, hij], [hij, klm]]
                final Collection<Set<String>> groups = Arrays.stream(orderHist).
                        map(o-> o.split(":")).
                        // for example map "first:abs" to ["first", "abc"] 
        
                        collect(Collectors.groupingBy(o-> o[0], 
                                Collectors.mapping(o-> o[1], Collectors.toSet()))).
                        values();
                        // group by customerId but keep only values (groups are 
                        // important but customer are not). 
        
                // get the set of strongly linked items
                final Set<String> stronglyLinkedItems = groups.stream().
                        flatMap(g-> g.stream()).
                        // we get someting like: [nop, tuv, klm, qrs, abc, abc, def, 
                        // hij]
        
                        filter(item-> !item.equals(itemId)).
                        // select only item != itemId
        
                        distinct().
                        // optimization. but stronglyLinked is not so costly (so may be 
                        // removed)
        
                        filter(item-> stronglyLinked(item, itemId, groups)).
                        // select only item strongly linked with item
        
                        collect(Collectors.toSet());
                        // make a set from that stream
        
                // weeklyLinked items
                final Set<String> weaklyLinkedItems = groups.stream().
                        flatMap(g-> g.stream()).
                        // we get someting like: [nop, tuv, klm, qrs, abc, abc, def, 
                        // hij]
        
                        filter(item-> !item.equals(itemId)).
                        // select only item != itemId
        
                        filter(item-> !stronglyLinkedItems.contains(item)).
                        // remove strongly linked items (alreay in stronglyLinkedItems
                        // set).
        
                        distinct().
                        // remove duplicate. it's only an optimization we don't want 
                        // to compute costly weaklyLinked() on duplicate (not needed).
        
                        filter(item-> weaklyLinked(item, itemId, groups)).
                        // select only item weakly linked with itemId
        
                        collect(Collectors.toSet());
                        // make a set 
        
                // return the result array
                return IntStream.of(
                        stronglyLinkedItems.size(), 
                        weaklyLinkedItems.size()).
                        toArray();
            }
        
            /**
             * main
             */
            public static void main(String[] args) {
                final String orderHist[] = {
                    "first:abc","first:hij", "second:hij", "second:klm", "third:nop",
                    "fourth:qrs", "fourth:abc", "first:def", "fifth:klm", "fifth:tuv"};
                int[] result = getLinkCount("abc", orderHist); 
                System.out.println(result[0]);
                System.out.println(result[1]);   
            }
        
            private static boolean weaklyLinked(String item1, String item2, 
                    Collection<Set<String>> groups, Set<Set<String>> bag) {
        
                // if (item1, item2) has already been explored then return false
                // this is needed to avoid infinite recursion
                if (bag.stream().anyMatch(s-> s.contains(item1) && s.contains(item2))) {
                    return false;
                }   
        
                // add (item1, item2) to the bag
                bag.add(Stream.of(item1, item2).collect(Collectors.toSet()));
        
                return groups.stream().
                        flatMap(g-> g.stream()).
                        // we get someting like:
                        // [nop, tuv, klm, qrs, abc, abc, def, hij]
        
                        filter(item-> !item.equals(item1) && !item.equals(item2)).
                        // filter for removing item1 and item2 from the stream
        
                        anyMatch(item-> (stronglyLinked(item1, item, groups) ||
                                weaklyLinked(item1, item, groups, new HashSet(bag))) &&
                                        (stronglyLinked(item2, item, groups) ||
                                weaklyLinked(item2, item, groups, new HashSet(bag))));
                        // any item strongly or weakly linked with item1 and item2 =>
                        // if yes return true
            }
        }
        
        包强;
        导入java.util.array;
        导入java.util.Collection;
        导入java.util.HashSet;
        导入java.util.Set;
        导入java.util.stream.collector;
        导入java.util.stream.IntStream;
        导入java.util.stream.stream;
        公众阶级的强势{
        /**
        *项目1和项目2是否有强链接?
        *@param item1第一项,例如“abc”
        *@param item2第二项,例如“hij”
        *@param组示例:[[nop],[tuv,klm],[qrs,abc],[abc,def,hij],
        *[你好,荷航]]
        *@如果item1和item2强链接,则返回true
        */
        公共静态布尔强链接(字符串项1、字符串项2、,
        (收集组){
        //如果组包含具有item1和item2的集合,则为true
        返回groups.stream()。
        任意匹配(g->g.contains(项目1)和&g.contains(项目2));
        }
        /**
        *项目1和项目2是否弱链接?
        *@param item1第一项,例如“abc”
        *@param item2第二项,例如“hij”
        *@param组示例:[[nop],[tuv,klm],[qrs,abc],[abc,def,hij],
        *[你好,荷航]]
        *@如果item1和item2弱链接,则返回true
        */
        公共静态布尔弱链接(字符串项1、字符串项2、,
        (收集组){
        //使用bag参数调用私有实现(以避免无限
        //递归)。
        返回弱链接(item1、item2、groups、newhashset());
        }
        /**
        *获取给定项的强链接计数和弱链接计数
        *@param itemId该项目
        *@param orderHist例如:{“first:abc”、“first:hij”、“second:hij”,
        *“第二:荷航”、“第三:nop”、“第四:qrs”、“第四:abc”、“第一:def”,
        *“第五:荷航”,“第五:图瓦”}
        *@返回一个具有[0]=>强链接计数、[1]=>弱链接计数的数组
        *伯爵。
        */
        公共静态int[]getLinkCount(字符串itemId,字符串[]orderHist){
        //获取一起购买的项目组,例如:
        //[[nop],[tuv,klm],[qrs,abc],[abc,def,hij],[hij,klm]]
        最终集合组=Arrays.stream(orderHist)。
        映射(o->o.split(“:”)。
        //例如,将“first:abs”映射到[“first”,“abc”]
        收集(收集器.分组方式(o->o[0],
        Collectors.mapping(o->o[1],Collectors.toSet())。
        值();
        //按customerId分组,但仅保留值(组为
        //重要,但客户不重要)。
        //获取强链接项集
        最终设置stronglyLinkedItems=groups.stream()。
        平面图(g->g.stream()。
        //我们得到的信息如下:[不,tuv,klm,qrs,abc,abc,def,
        //hij]
        筛选器(item->!item.equals(itemId))。
        //仅选择项目!=项目ID
        独特的()。
        //优化。但stronglyLinked的成本并不高(也可能如此)
        //删除)
        筛选(项目->强链接(项目、项目ID、组))。
        //仅选择与项目强链接的项目
        收集(collector.toSet)