program tip

건초 더미에서 바늘을 어떻게 찾습니까?

radiobox 2020. 10. 23. 07:45
반응형

건초 더미에서 바늘을 어떻게 찾습니까?


객체 지향 방식으로 건초 더미의 바늘 검색을 구현할 때 기본적으로 세 가지 대안이 있습니다.

1. needle.find(haystack)

2. haystack.find(needle)

3. searcher.find(needle, haystack)

어떤 것을 선호하며 그 이유는 무엇입니까?

어떤 사람들은 세 번째 개체를 도입하지 않기 때문에 두 번째 대안을 선호한다는 것을 알고 있습니다. 그러나 적어도 "실제 세계"를 모델링하는 것이 목표라면 세 번째 접근 방식이 개념적으로 "정확하다"는 느낌을받을 수 없습니다.

이 예에서 검색 자와 같은 도우미 개체를 도입하는 것이 정당하다고 생각하는 경우, 언제 피해야합니까?


일반적으로 작업은 작업중인 작업에 적용되어야합니다.이 경우 건초 더미이므로 옵션 2가 가장 적절하다고 생각합니다.

또한 대안 3보다 낫다고 생각하는 네 번째 대안이 있습니다.

haystack.find(needle, searcher)

이 경우 작업의 일부로 검색하려는 방식을 제공 할 수 있으므로 작업중인 개체와 함께 작업을 유지할 수 있습니다.


세 가지 중 옵션 # 3을 선호합니다.

원리는 단일 책임 있게 나를 내 DTO들 또는 모델의 기능을 검색 넣어 싶지 않다. 그들의 책임은 데이터가되는 것이지 자신을 찾는 것이 아니라 바늘이 건초 더미에 대해 알 필요가없고 건초 더미가 바늘에 대해 알 필요가 없어야합니다.

그만한 가치가 있기 때문에, 나는 왜 # 3이 최선의 선택인지 이해하는 데 대부분의 OO 실무자들이 오랜 시간이 걸린다고 생각합니다. 나는 10 년 동안 OO를했는데, 아마 내가 정말로 그로 킹하기 전에.

@wilhelmtell, C ++는 이러한 시스템이 실제로 작동하도록하는 템플릿 전문화를 가진 몇 안되는 언어 중 하나입니다. 대부분의 언어에서 범용 "찾기"방법은 끔찍한 아이디어입니다.


C ++의 STL에서 사용하는 접근 방식 인 또 다른 대안이 있습니다.

find(haystack.begin(), haystack.end(), needle)

C ++이 "당신의 얼굴에!"라고 외치는 훌륭한 예라고 생각합니다. OOP에. 아이디어는 OOP가 어떤 종류의 은총이 아니라는 것입니다. 때로는 행동 측면에서, 때로는 객체 측면에서, 때로는 둘 다 또는 둘 다로 가장 잘 설명됩니다.

Bjarne Stroustrup은 TC ++ PL에서 시스템을 설계 할 때 효과적이고 효율적인 코드의 제약하에 현실을 반영하도록 노력해야한다고 말했습니다. 나를 위해 이것은 당신이 어떤 것도 맹목적으로 따라 가서는 안된다는 것을 의미합니다. 당면한 것들 (건초 더미, 바늘)과 우리가 속한 맥락 (검색, 그것이 표현의 의미)에 대해 생각해보십시오.

검색에 중점을 두는 경우 검색을 강조하는 알고리즘 (액션)을 사용합니다 (즉, 건초 더미, 바다, 사막, 연결 목록에 유연하게 맞출 수 있음). 강조가 건초 더미에 관한 것이라면 건초 더미 객체 안에 find 메서드를 캡슐화하는 식입니다.

즉, 때때로 의심스럽고 선택하기가 어렵습니다. 이 경우 객체 지향적이어야합니다. 나중에 마음이 바뀌면 객체에서 액션을 추출한 다음 액션을 객체와 클래스로 나누는 것이 더 쉽다고 생각합니다.

이 지침을 따르면 코드가 더 명확하고 아름답습니다.


나는 옵션 1이 완전히 나왔다고 말할 것입니다. 코드는 그것이하는 일을 알려주는 방식으로 읽어야합니다. 옵션 1은이 바늘이 나에게 건초 더미를 찾을 것이라고 생각하게합니다.

건초 더미에 바늘이 포함되어 있으면 옵션 2가 좋아 보입니다. ListCollections는 항상 ListItems를 포함하므로 collection.find (item)는 자연스럽고 표현력이 좋습니다.

다음과 같은 경우 도우미 개체를 도입하는 것이 적절하다고 생각합니다.


  1. IE : search.find (ObsecureOSObject, file) 에서 개체의 구현을 제어하지 않습니다 .
  2. 개체
    IE : nameMatcher.find (houses, trees.name) 간에 규칙적이거나 합리적인 관계가 없습니다.

나는 이것에 대해 Brad와 함께있다. 엄청나게 복잡한 시스템에서 작업할수록 객체를 진정으로 분리해야 할 필요성이 커집니다. 그가 맞아. 바늘이 건초 더미에 대해 아무것도 몰라 야한다는 것은 명백하므로 1은 확실히 나옵니다. 그러나 건초 더미는 바늘에 대해 아무것도 몰라 야합니다.

건초 더미를 모델링하는 경우 바늘 모음이 아닌 건초 또는 모음으로 구현할 수 있습니다 ! 그러나 나는 건초 더미에서 물건을 잃어버린다는 것을 고려할 것이지만 정확히 그 물건에 대해서는 아무것도 모릅니다. 건초 더미가 항목 자체를 찾지 않는 것이 좋습니다 ( 어쨌든 건초 더미가 얼마나 똑똑한 지 ). 나에게 올바른 접근 방식은 건초 더미가 그 안에 있지만 짚이나 건초가 아니거나 건초 더미에 본질을 부여하는 것이 아닌 물건 모음을 제시하는 것입니다.

class Haystack : ISearchableThingsOnAFarm {
   ICollection<Hay> myHay;
   ICollection<IStuffSmallEnoughToBeLostInAHaystack> stuffLostInMe;

   public ICollection<Hay> Hay {
      get {
         return myHay;
      }
   }

   public ICollection<IStuffSmallEnoughToBeLostInAHayStack> LostAndFound {
      get {
        return stuffLostInMe;
      }
   }
}

class Needle : IStuffSmallEnoughToBeLostInAHaystack {
}

class Farmer {
  Search(Haystack haystack, 
                 IStuffSmallEnoughToBeLostInAHaystack itemToFind)
}

실제로 인터페이스에 타이핑하고 추상화 할 것이 더 많았습니다. 그리고 나서 제가 얼마나 미친 짓인지 깨달았습니다. 내가 대학에서 CS 수업을 듣는 것 같은 느낌 ... : P

당신은 아이디어를 얻습니다. 가능한 한 느슨하게 연결되는 것이 좋은 것이라고 생각합니다. :)


Needle과 Haystack이 모두 DAO라면 옵션 1과 2는 문제가되지 않습니다.

그 이유는 DAO가 모델링중인 실제 객체의 속성 만 보유하고 getter 및 setter 메서드 (또는 직접 속성 액세스) 만 가져야하기 때문입니다. 이렇게하면 DAO를 파일로 직렬화하거나 일반 비교 / 일반 복사를위한 메서드를 작성하기가 더 쉬워집니다. 코드에 이러한 도우미 메서드를 건너 뛰기위한 "if"문 전체가 포함되어 있지 않기 때문입니다.

이것은 옵션 3을 남겨두고 대부분이 올바른 행동에 동의합니다.

옵션 3에는 몇 가지 장점이 있으며 가장 큰 장점은 단위 테스트입니다. 이것은 Needle과 Haystack 객체를 모두 쉽게 조롱 할 수있는 반면, 옵션 1 또는 2가 사용 된 경우 검색을 수행하기 전에 Needle 또는 Haystack의 내부 상태를 수정해야하기 때문입니다.

둘째, 검색자가 이제 별도의 클래스에 있으므로 공통 검색 코드를 포함하여 모든 검색 코드를 한곳에 보관할 수 있습니다. 검색 코드가 DAO에 포함 된 경우 일반적인 검색 코드는 복잡한 클래스 계층 구조에 저장되거나 어쨌든 Searcher Helper 클래스와 함께 저장됩니다.


이것은 전적으로 무엇이 다르고 무엇이 동일하게 유지되는지에 달려 있습니다.

예를 들어, 바늘 유형과 건초 더미에 따라 찾기 알고리즘이 다른 (비 OOP) 프레임 워크 에서 작업하고 있습니다. 이 외에도이 객체 지향 환경에서 이중 파견을 필요로한다는 사실에서, 그것은 또한 중 하나를 작성하는 의미가 없다는 것을 의미 needle.find(haystack)나 쓰기에 haystack.find(needle).

반면에 애플리케이션은 두 클래스 중 하나에 결과를 기꺼이 위임하거나 하나의 알고리즘을 모두 고수 할 수 있으며이 경우 결정이 임의적입니다. 이 경우 haystack.find(needle)건초 더미에 결과를 적용하는 것이 더 논리적으로 보이기 때문에 방법을 선호합니다 .


객체 지향 방식으로 건초 더미의 바늘 검색을 구현할 때 기본적으로 세 가지 대안이 있습니다.

  1. needle.find (건초 더미)

  2. haystack.find (바늘)

  3. searcher.find (needle, haystack)

어떤 것을 선호하며 그 이유는 무엇입니까?

내가 틀렸다 있지만, 모든 세 가지 예에 이미있는 경우 나 수정 가 코에 앉아있을 때 그래서이 안경을 찾고처럼 좀하지, 당신이 찾고있는 바늘에 대한 참조를? :피

제쳐두고, 건초 더미의 책임이 주어진 도메인 내에 있다고 생각하는 것에 달려 있다고 생각합니다. 바늘을 포함하는 것 (본질적으로 컬렉션)이라는 의미에서 우리는 그것에 대해 신경을 쓰는가? 그러면 haystack.find (needlePredicate)가 좋습니다. 그렇지 않으면 farmBoy.find (predicate, haystack)이 더 적절할 수 있습니다.


SICP 의 위대한 저자를 인용하기 위해 ,

프로그램은 사람들이 읽을 수 있도록 작성되어야하며, 기계가 실행되도록 부수적으로 만 작성되어야합니다.

나는 방법 1과 2를 모두 가지고있는 것을 선호한다. 루비를 예로 들어 보면 다음과 .include?같이 사용됩니다.

haystack.include? needle
=> returns true if the haystack includes the needle

하지만 때로는 가독성을 위해 순전히 뒤집고 싶습니다. Ruby에는 in?메소드가 없지만 한 줄짜리이므로 자주 이렇게합니다.

needle.in? haystack
=> exactly the same as above

건초 더미 또는 검색 작업을 강조하는 것이 "더 중요"하다면 include?. 그러나 종종 건초 더 미나 검색이 실제로 관심있는 것이 아닙니다. 객체가 존재하기 만하면됩니다.이 경우 in?프로그램의 의미를 더 잘 전달합니다.


귀하의 요구 사항에 따라 다릅니다.

예를 들어 검색 자의 속성 (예 : 검색 자의 강도, 시력 등)에 관심이 없다면 haystack.find (needle)이 가장 깨끗한 솔루션이라고 말할 수 있습니다.

그러나 검색 자의 속성 (또는 해당 문제에 대한 다른 속성)에 관심이 있다면 ISearcher 인터페이스를 건초 더미 생성자 또는 함수에 삽입하여이를 용이하게합니다. 이것은 객체 지향 설계 (건초 더미에 바늘이 있음)와 제어 반전 / 종속성 주입 ( "찾기"기능의 단위 테스트를 더 쉽게 함)을 모두 지원합니다.


처음 두 가지 맛 중 하나가 의미가있는 상황을 생각할 수 있습니다.

  1. 니들 필요가 누스 모리스 - 프랫 알고리즘에서와 같이, 사전 처리하는 경우 needle.findIn(haystack)(또는 pattern.findIn(text)니들 객체가 효과적으로 작동하기 위해 알고리즘 생성 중간 테이블을 보유하고 있기 때문에), 말이

  2. 건초 더미에 사전 처리가 필요한 경우 (예 : trie ) haystack.find(needle)(또는 words.hasAWordWithPrefix(prefix))가 더 잘 작동합니다.

위의 두 경우 모두 needle 또는 haystack 중 하나가 검색을 인식합니다. 또한 둘 다 서로를 알고 있습니다. 바늘과 건초 더미가 서로 또는 수색을 인식하지 못하도록하려면 searcher.find(needle, haystack)적절할 것입니다.


쉬움 : 건초 더미를 태워라! 그 후에는 바늘 만 남게됩니다. 또한 자석을 사용해 볼 수 있습니다.

더 어려운 질문 : 바늘 풀에서 특정 바늘을 어떻게 찾을 수 있습니까?

답 : 각각을 스레드하고 각 스레드 가닥의 다른 쪽 끝을 정렬 된 인덱스 (예 : 포인터)에 연결합니다.


이 질문에 대한 답은 실제로 솔루션이 구현되는 도메인에 따라 달라집니다.
물리적 건초 더미에서 물리적 검색을 시뮬레이션하는 경우 클래스가있을 수 있습니다.

  • 우주
  • 빨대
  • 바늘
  • 시커

공간 은 자연의 법칙을 구현
하는 좌표
(에너지 변환, 충돌 감지 등)에 어떤 물체가 있는지 알고 있습니다 .

바늘 , 밀짚
은 공간에 위치
하여 힘에 반응

시커
는 공간과 상호 작용합니다 :
    손을 움직이고, 자기장을 적용하고, 건초를 태우고, 엑스레이를 적용하고, 바늘을 찾습니다 .

따라서   seeker.find(needle, space)   또는   seeker.find(needle, space, strategy)

건초 더미는 바늘을 찾는 공간에 있습니다. 공간을 일종의 가상 머신으로 추상화 할 때 (행렬을 생각해보십시오) 공간 대신 ​​건초 더미를 사용하여 위의 결과를 얻을 수 있습니다 (솔루션 3 / 3b) .

seeker.find(needle, haystack)     또는     seeker.find(needle, haystack, strategy)

그러나 매트릭스는 도메인이었으며 바늘이 다른 곳에있을 수없는 경우 건초 더미로만 대체되어야합니다.

그리고 다시 말하지만 그것은 단지 변증이었습니다. 흥미롭게도 이것은 완전히 새로운 방향에 대한 마음을 열어줍니다.
1. 처음에 바늘을 푼 이유는 무엇입니까? 프로세스를 변경할 수 있으므로 느슨해지지 않습니까?
2. 잃어버린 바늘을 찾아야합니까 아니면 다른 바늘을 구하고 첫 번째 바늘을 잊어 버릴 수 있습니까? (그렇다면 잠시 후 바늘이 녹 으면 좋을 것입니다.)
3. 바늘을 정기적으로 풀고 다시 찾아야 할 경우에는

  • 스스로를 찾을 수있는 바늘을 만드십시오. 예를 들어 그들은 정기적으로 스스로에게 묻습니다. 내가 길을 잃었습니까? 대답이 '예'인 경우 GPS에서 계산 한 위치를 누군가에게 보내거나 경고음 등을 울리기 시작합니다.
    needle.find(space)또는 needle.find(haystack)    (해결 방법 1)

  • 각 빨대에 카메라가 달린 건초 더미를 설치 한 후 최근에 바늘을 보았는지 건초 더미 벌집 마음에 물어볼 수 있습니다 :
    haystack.find (needle) (해결 방법 2)

  • 바늘에 RFID 태그를 부착하여 쉽게 삼각 측량 할 수 있습니다.

그것은 당신의 구현 에서 바늘과 건초 더미 만들었고 대부분의 경우 어떤 수준의 매트릭스 만들었다 고 말하는 것입니다 .

따라서 도메인에 따라 결정하십시오.

  • 바늘을 포함하는 것이 건초 더미의 목적입니까? 그런 다음 솔루션 2로 이동하십시오.
  • 바늘이 어디에서나 손실되는 것이 당연한가요? 그런 다음 솔루션 1로 이동하십시오.
  • 바늘이 건초 더미에서 우연히 길을 잃었습니까? 그런 다음 해결 방법 3으로 이동합니다 (또는 다른 복구 전략 고려).

haystack.find (needle), 검색 자 필드가 있어야합니다.

의존성 주입이 모든 분노라는 것을 알고 있으므로 @Mike Stone의 haystack.find (needle, searcher)가 수락 된 것은 놀라운 일이 아닙니다. 그러나 나는 동의하지 않습니다. 어떤 검색자가 사용되는지에 대한 선택은 건초 더미에 대한 결정으로 보입니다.

두 개의 ISearcher를 고려하십시오. MagneticSearcher는 자석의 강도와 일치하는 방식으로 자석을 이동하고 밟아 볼륨을 반복합니다. QuickSortSearcher는 바늘이 하위 파일 중 하나에서 분명해질 때까지 스택을 두 개로 나눕니다. 검색 자의 적절한 선택은 건초 더미가 얼마나 큰지 (예 : 자기장에 비해), 바늘이 건초 더미에 어떻게 들어 갔는지 (예 : 바늘의 위치가 정말로 무작위입니까, 아니면 편향되어 있습니까?) 등에 따라 달라질 수 있습니다.

haystack.find (needle, searcher)가있는 경우 "가장 좋은 검색 전략을 선택하는 것이 건초 더미의 컨텍스트 밖에서 수행하는 것이 가장 좋습니다."라고 말하는 것입니다. 나는 그것이 옳을 것 같지 않다고 생각합니다. 나는 "건초 더미가 자신을 검색하는 가장 좋은 방법을 알고"있을 가능성이 더 높다고 생각합니다. setter를 추가하고 재정의하거나 테스트해야하는 경우 검색자를 수동으로 삽입 할 수 있습니다.


개인적으로 저는 두 번째 방법을 좋아합니다. 내 추론은 내가 함께 작업 한 주요 API가이 접근 방식을 사용하기 때문이며 가장 합리적이라고 생각합니다.

물건 목록 (haystack)이 있으면 바늘을 검색합니다 (find ()).


@Peter Meyer

당신은 아이디어를 얻습니다. 가능한 한 느슨하게 연결되는 것이 좋은 것이라고 생각합니다. :)

음 ... 예 ... 제 생각 엔 그게 IStuffSmallEnoughToBeLostInAHaystack적기 인 것 같아요 :-)


또한 대안 3보다 낫다고 생각하는 네 번째 대안이 있습니다.

haystack.find(needle, searcher)

나는 당신의 요점을 알지만 searcher건초 더미 이외의 다른 유형의 객체를 검색하고 바늘 이외의 다른 것을 찾을 수있는 검색 인터페이스를 구현하면 어떨까요?

인터페이스는 다른 알고리즘으로 구현 될 수도 있습니다. 예를 들면 다음과 같습니다.

binary_searcher.find(needle, haystack)
vision_searcher.find(pitchfork, haystack)
brute_force_searcher.find(money, wallet)

그러나 다른 사람들이 이미 지적했듯이 이것은 실제로 여러 검색 알고리즘 또는 여러 검색 가능하거나 찾을 수있는 클래스가있는 경우에만 유용하다고 생각합니다. 그렇지 않다면, 나는 haystack.find(needle)그것의 단순성 때문에 더 낫다는 것에 동의한다 . 그래서 나는 그것을 위해 약간의 "정확성"을 기꺼이 희생 할 것이다.


class Haystack {//whatever
 };
class Needle {//whatever
 }:
class Searcher {
   virtual void find() = 0;
};

class HaystackSearcher::public Searcher {
public:
   HaystackSearcher(Haystack, object)
   virtual void find();
};

Haystack H;
Needle N;
HaystackSearcher HS(H, N);
HS.find();

정말 2와 3의 혼합.

일부 건초 더미에는 특수한 검색 전략이 없습니다. 이것의 예는 배열입니다. 무언가를 찾는 유일한 방법은 처음부터 시작하여 원하는 항목을 찾을 때까지 각 항목을 테스트하는 것입니다.

이런 종류의 경우 무료 함수가 아마도 가장 좋습니다 (예 : C ++).

일부 건초 더미에는 특수 검색 전략이 적용될 수 있습니다. 예를 들어 이진 검색을 사용할 수 있도록 배열을 정렬 할 수 있습니다. 자유 함수 (또는 한 쌍의 자유 함수, 예를 들어 sort 및 binary_search)가 아마도 최상의 옵션 일 것입니다.

일부 건초 더미에는 구현의 일부로 통합 검색 전략이 있습니다. 예를 들어, 연관 컨테이너 (해시 또는 정렬 된 세트 및 맵)는 모두 수행됩니다. 이 경우, 찾기는 아마도 필수적인 조회 방법 일 것입니다. 그래서 그것은 아마도 방법, 즉 haystack.find (needle)이어야합니다.


건초 더미는 물건을 포함 할 수 있습니다. 한 가지 유형의 물건은 바늘 찾기입니다. 물건 찾기를 담당하는 물건 찾기 도구는 물건을 찾을 수있는 소스로 물건 더미를받을 수 있습니다.

따라서 가급적 유연한 솔루션의 경우 다음과 같이 할 수 있습니다. IStuff 인터페이스

Haystack = IList <IStuff> 바늘 : IStuff

Finder .Find (IStuff stuffToLookFor, IList <IStuff> stuffsToLookIn)

이 경우 솔루션은 바늘과 건초 더미에만 묶이지 않지만 인터페이스를 구현하는 모든 유형에 사용할 수 있습니다.

바다에서 물고기를 찾고 싶다면 할 수 있습니다.

var results = Finder.Find (물고기, 바다)


바늘 물체에 대한 참조가 있다면 왜 그것을 검색합니까? :) 문제 도메인과 사용 사례는 건초 더미에서 바늘의 정확한 위치가 필요하지 않다고 말합니다 (list.indexOf (element)에서 얻을 수있는 것과 같은), 바늘 만 있으면됩니다. 그리고 당신은 아직 그것을 가지고 있지 않습니다. 그래서 내 대답은 다음과 같습니다.

Needle needle = (Needle)haystack.searchByName("needle");

또는

Needle needle = (Needle)haystack.searchWithFilter(new Filter(){
    public boolean isWhatYouNeed(Object obj)
    {
        return obj instanceof Needle;
    }
});

또는

Needle needle = (Needle)haystack.searchByPattern(Size.SMALL, 
                                                 Sharpness.SHARP, 
                                                 Material.METAL);

나는 다른 검색 전략을 기반으로하는 더 많은 가능한 해결책이 있다는 것에 동의한다. 그래서 그들은 검색자를 소개한다. 이것에 대한 충분한 코멘트가 있었기 때문에 여기서는 신경 쓰지 않습니다. 내 요점은 위의 솔루션이 유스 케이스를 잊어 버리는 것입니다. 이미 참조가있는 경우 검색 할 요점이 무엇입니까? 가장 자연스러운 사용 사례에서는 아직 바늘이 없으므로 가변 바늘을 사용하지 않습니다.


Brad Wilson points out that objects should have a single responsibility. In the extreme case, an object has one responsibility and no state. Then it can become... a function.

needle = findNeedleIn(haystack);

Or you could write it like this:

SynchronizedHaystackSearcherProxyFactory proxyFactory =
    SynchronizedHaystackSearcherProxyFactory.getInstance();
StrategyBasedHaystackSearcher searcher =
    new BasicStrategyBasedHaystackSearcher(
        NeedleSeekingStrategies.getMethodicalInstance());
SynchronizedHaystackSearcherProxy proxy =
    proxyFactory.createSynchronizedHaystackSearcherProxy(searcher);
SearchableHaystackAdapter searchableHaystack =
    new SearchableHaystackAdapter(haystack);
FindableSearchResultObject foundObject = null;
while (!HaystackSearcherUtil.isNeedleObject(foundObject)) {
    try {
        foundObject = proxy.find(searchableHaystack);
    } catch (GruesomeInjuryException exc) {
        returnPitchforkToShed();  // sigh, i hate it when this happens
        HaystackSearcherUtil.cleanUp(hay); // XXX fixme not really thread-safe,
                                           // but we can't just leave this mess
        HaystackSearcherUtil.cleanup(exc.getGruesomeMess()); // bug 510000884
        throw exc; // caller will catch this and get us to a hospital,
                   // if it's not already too late
    }
}
return (Needle) BarnyardObjectProtocolUtil.createSynchronizedFindableSearchResultObjectProxyAdapterUnwrapperForToolInterfaceName(SimpleToolInterfaces.NEEDLE_INTERFACE_NAME).adapt(foundObject.getAdaptable());

The haystack shouldn't know about the needle, and the needle shouldn't know about the haystack. The searcher needs to know about both, but whether or not the haystack should know how to search itself is the real point in contention.

So I'd go with a mix of 2 and 3; the haystack should be able to tell someone else how to search it, and the searcher should be able to use that information to search the haystack.


haystack.magnet().filter(needle);

Is the code trying to find a specific needle or just any needle? It sounds like a stupid question, but it changes the problem.

Looking for a specific needle the code in the question makes sense. Looking for any needle it would be more like

needle = haystack.findNeedle()

or

needle = searcher.findNeedle(haystack)

Either way, I prefer having a searcher that class. A haystack doesn't know how to search. From a CS perspective it is just a data store with LOTS of crap that you don't want.


Definitely the third, IMHO.

The question of a needle in a haystack is an example of an attempt to find one object in a large collection of others, which indicates it will need a complex search algorithm (possibly involving magnets or (more likely) child processes) and it doesn't make much sense for a haystack to be expected to do thread management or implement complex searches.

A searching object, however, is dedicated to searching and can be expected to know how to manage child threads for a fast binary search, or use properties of the searched-for element to narrow the area (ie: a magnet to find ferrous items).


Another possible way can be to create two interfaces for Searchable object e.g. haystack and ToBeSearched object e.g. needle. So, it can be done in this way

public Interface IToBeSearched
{}

public Interface ISearchable
{

    public void Find(IToBeSearched a);

}

Class Needle Implements IToBeSearched
{}

Class Haystack Implements ISearchable
{

    public void Find(IToBeSearched needle)

   {

   //Here goes the original coding of find function

   }

}

haystack.iterator.findFirst(/* pass here a predicate returning
                               true if its argument is a needle that we want */)

iterator can be interface to whatever immutable collection, with collections having common findFirst(fun: T => Boolean) method doing the job. As long as the haystack is immutable, no need to hide any useful data from "outside". And, of course, it's not good to tie together implementation of a custom non-trivial collection and some other stuff that does have haystack. Divide and conquer, okay?


In most cases I prefer to be able to perform simple helper operations like this on the core object, but depending on the language, the object in question may not have a sufficient or sensible method available.

Even in languages like JavaScript) that allow you to augment/extend built-in objects, I find it can be both convenient and problematic (e.g. if a future version of the language introduces a more efficient method that gets overridden by a custom one).

This article does a good job of outlining such scenarios.

참고URL : https://stackoverflow.com/questions/23755/how-do-you-find-a-needle-in-a-haystack

반응형