2011-08-04 4 views
2

Norvig's book on AIP을 통해 진행 중입니다.교차 상품 계산기 Java

(defun cross-product (fn list-1 list-2) 
    (mappend #'(lambda (y) 
       (mapcar #'(lambda (x) 
          (funcall fn y x)) 
         list-2)) 
      list-1)) 

(defun mappend (fn the-list) 
    (if (null the-list) 
     nil 
     (append (funcall fn (first the-list)) 
       (mappend fn (rest the-list))))) 

내가 자바의 구현을 작성하는 것을 시도하고있다 - - 제품 간 기능을 작성하는 방법에 그것에 운동이

interface Function<T1, T2, T3> { 
    public T3 function(T1 t1, T2 t2); 
} 

public class CrossProduct<T1, T2> { 
    private List<T1> list1; 
    private List<T2> list2; 

    public CrossProduct(List<T1> t1, List<T2> t2) { 
     this.list1 = t1; 
     this.list2 = t2; 
    } 

    public <T3> List<T3> calculate(Function<T1, T2, T3> fn) { 
    List product = new ArrayList(); 
    for (int i = 0; i < list1.size(); i++) 
     for (int j = 0; j < list2.size(); j++) 
      product.add(fn.function(list1.get(i), list2.get(j))); 
    return product; 
} 

은}

사용 -

@Test 
public void testWithStrings() { 
    List<String> list1 = new ArrayList<String>(); 
    list1.add("6"); 
    list1.add("8"); 

    List<String> list2 = new ArrayList<String>(); 
    list2.add("2"); 
    list2.add("3"); 

    List<String> product = new CrossProduct<String, String>(list1, list2) 
      .<String> calculate(new Function<String, String, String>() { 
       public String function(String x, String y) { 
        return (String) x + (String) y; 
       } 

      }); 

    Assert.assertEquals("62", product.get(0)); 
    Assert.assertEquals("63", product.get(1)); 
    Assert.assertEquals("82", product.get(2)); 
    Assert.assertEquals("83", product.get(3)); 
} 

더 좋은 방법이 있나요?

답변

1

CrossProduct 클래스를 정의하는 것은 약간 임의적입니다. 목록에 구성원 변수가있는 이유는 무엇입니까? 반면 fn은 메서드 매개 변수입니까? 사실 CrossProduct은 왜 수업에 참여합니까? 주어진 목록이 모두

  1. 은 여러 가지 방법으로 외적으로 표현 될 수 있으며,
  2. crossproduct 기능을 사용하여 구성되지 않았을 때문에 크로스 제품 is a 목록은,하지만,리스트의 하위 유형이 아닙니다.

"크로스 제품"을 유형으로 생각하는 것은 자연스럽지 않습니다. 당신이 (예 살만이 제안 게으른 평가를 구현하는) 어떤 이유로 클래스 CrossProduct을 정의 할 않은 경우

아마 나는 세 가지를 더 OO 말할 것이다,

public class ListFunctions { 
    public static <T1, T2, T3> List<T3> crossProduct(List<T1> list1, List<T2> list2, Function<T1, T2, T3> fn) { 
     List<T3> product = new ArrayList<T3>(); 
     for (int i = 0; i < list1.size(); i++) 
      for (int j = 0; j < list2.size(); j++) 
      product.add(fn.function(list1.get(i), list2.get(j))); 
     return product; 
    } 
} 

과 같이 할 것 args를 멤버 변수로 사용하고 클래스를 구현하려면 List, 예

public class CrossProduct<T1, T2, T3> implements List<T3> { 
    public CrossProduct(T1 list1, T2 list2, Function<T1, T2, T3> fn) { 
     // remember args... 
    } 
    // etc... 
} 
+0

감사! 둘 다 개선되었습니다. – user869081

1

어떤 매개 변수를 개선하고 싶은지 정확하게 알지 못합니다. 그러나 너무 큽니다 때문에 N * M 목록 크기가 마음에 들지 않습니다. 결과 목록을 변경할 수 없다는 것을 알았다면 result.get(i*M+j-1)이 호출 될 때 product(l1(i), l2(j)) 만 계산하는 자체 List를 구현할 것입니다. 그래서 나는 긴 목록 (아마도 필요한 경우 작은 캐시)을 지키지 않았다.