2016-10-02 82 views
-1

如果同一客戶購買了兩個產品,則兩個產品有很強的關聯。如果兩個項目與第三個項目強有力或弱相關,則兩個項目之間的聯繫較弱。根據客戶歷史記錄查找強大和薄弱的鏈接

輸入:

{"first:abc","first:hij", "second:hij", "second:klm", "third:nop","fourth:qrs", "fourth:abc", "first:def", "fifth:klm", "fifth:tuv"}

「第一/二/三/第四/五」 是cutomerID而 「ABC,HIJ」 ECT是項ID。他們被一個「:」分隔。

目標:查找給定項目的強和弱鏈接的數量。

示例:對於 「ABC」 和字符串的上述輸入陣列輸出應該是

[3,2]

的密切聯繫是QRS,HIJ,DEF和薄弱環節是KLM,TUV

方法:

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

} 

我已經能夠搞清楚的是:雖然陣列

  1. 步行街和爲每個客戶建立一個項目列表。 所以基本上它是一個客戶的HashMap。 Key將是 customerID,值將是itemID的ArrayList
  2. 對於HapMap中的每個 項目,檢查數組列表是否具有itemId。如果是,則返回arrayList並將這些itemId存儲在strongLinks數組中。
  3. 刪除strongList數組中的重複項。現在你有一個給定itemId的強大 鏈接。你可以返回計數。

不知道這是否是最有效的。還堅持現在如何找到弱鏈接

回答

1

我目前沒有IDE,所以現在我無法提供完整的程序,但我試圖概述這個想法。尋找強大的鏈接看起來總體上可以像你一樣行事,但是你可能更好地將它與通過遍歷你的hashmap同時找到薄弱環節合併起來,從那些客戶的項目列表包含特定元素

在這種情況下,客戶的「第一」,並在他們的項目列表

  • 客戶「第一」也有項目「HIJ」和「DEF」,在他的名單「第四」有項目「ABC」,這些都是與「ABC」有很強的聯繫。因此,應該繼續搜索那些項目列表包含這些元素的客戶。在這種情況下,客戶「第二」也有項目「HIJ」,此外他還有「KLM」,所以「KLM」是與「ABC」的薄弱環節。沒有任何其他客戶的項目列表中有「DEF」,因此我們在此停止。您應該繼續搜索那些項目列表中包含「KLM」的客戶,並且您還會發現客戶「第五」,其項目列表中還包含「TUV」,這也是「ABC」的薄弱環節。沒有任何其他客戶的產品列表中有「TUV」,因此我們在此停止。

  • 客戶「第四」有項目「QRS」,它是「ABC」的強有力鏈接。沒有任何其他客戶的項目列表中有「QRS」,因此我們在此停止。

+0

我知道這味道聞起來像一個遞歸解決方案....如果你訪問一個IDE我將不勝感激一些代碼提示...反正也讓我在這方面努力。 – codeNinja

1

這裏是一個工作版本。請參閱代碼中的註釋:

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 
    } 
} 
+0

這很好。有沒有辦法做到這一點核心對象像數組/鏈接列表?我認爲使用集合及其所有奇特的方法違背了硬件問題的本質。他們真的想讓你思考和解決。 – codeNinja

+0

是的,我用java 8 lambda表達式。這不是幻想,但不同(功能編程)。如果您編寫併發布代碼以進行強連接(非常容易)。我會爲你做一個弱鏈接,我將以純粹的命令形式使用你的數據結構。 –