2015-09-01 11 views
19

मेरे पास फ़ाइल पथों की सूची है:।किसी अन्य सूची के आधार पर लैम्ब्डा के साथ सूची से तत्वों को कैसे निकालें

List<Path> filePaths; //e.g. [src\test\resources\file\15\54\54_exampleFile.pdf] 

54 ऊपर आईडी दर्ज करने के लिए संदर्भित करता है

मैं तो String आईडी जो अपने आवेदन के रूप में संभाल कर सकते हैं इस प्रकार की एक Set प्राप्त:

Set<String> acceptedIds = connection.getAcceptedIDs(); //e.g. elements [64, 101, 33] 

मैं filter बाहर करने के लिए जावा 8 lambdas उपयोग कर सकते हैं कैसे filePaths में सभी तत्व जिनमें acceptedIds संग्रह सेट में शामिल स्वीकार्य आईडी शामिल नहीं हैं।

दूसरे शब्दों में, मैं filePaths में केवल उन पथों को बनाए रखना चाहता हूं जिनमें acceptedIds सेट हैं। उदाहरण के लिए, 54 उपरोक्त सूची में नहीं है इसलिए हटा दिया गया है।

filePaths.stream().filter(...).collect(Collectors.toList()); 
+1

क्या हम आईडी के नाम पर तत्काल मूल निर्देशिका पर भरोसा कर सकते हैं? – Bohemian

+4

filePaths.removeIf (पी ->! स्वीकृत आईडीएस कॉन्टैन्स (पी .getPath()) –

उत्तर

22

लिए सबसे कारगर तरीका पथ से आईडी प्राप्त है, तो सेट में यह पता लगाने के लिए प्रयास करते हैं, प्रत्येक फिल्टर निरंतर समय में निष्पादित, यानी O(1) एक समग्र O(n) दे रही है बनाने के लिए है

filePaths.stream() 
    .filter(p -> acceptedIds.contains(p.getParent().getFileName().toString())) 
    .collect(Collectors.toList()); 

तो रिवर्स दृष्टिकोण से किया जाता है, जहां प्रत्येक acceptedIds रास्ते में के लिए खोज की है (अन्य उत्तर के रूप में), प्रत्येक फिल्टर, whe O(m*k) है:, जहां n रास्तों की संख्या है macceptedIds और k की औसत पथ लंबाई है, जो कुल O(n * m * k) प्रदान करती है, जो कि मध्यम आकार के संग्रहों के लिए भी बहुत खराब प्रदर्शन करेगी।

+0

निकालने के दौरान सफेद स्थानों के लिए आईडी को कैसे ट्रिम करना चाहिए? – user2781389

+0

व्हाइटस्पेस कहां है? पथ में, उदाहरण के लिए '' src \ test \ resource \ file \ 15 \ 54 \ 54_exampleFile.pdf "' (निर्देशिका का नाम '54" '- एक स्थान के साथ), या 'स्वीकृत आईडी' में संग्रहीत मानों में? – Bohemian

+0

'acceptIds' – user2781389

3

आप लिख सकते हैं:

filePaths.stream() 
     .filter(p -> acceptedIds.stream().anyMatch(id -> p.toString().contains(id))) 
     .collect(toList()); 

यह प्रत्येक पथ ऐसी है कि acceptedIds कम से कम एक पथ की स्ट्रिंग प्रतिनिधित्व में निहित है फिल्टर। आप अपने उपयोग-मामले (उदाहरण के लिए फ़ाइल नाम की शुरुआत से मेल खाते हुए) के आधार पर contains से बेहतर कुछ बेहतर कार्यान्वित करना चाहेंगे।

anyMatch एक ऐसा ऑपरेशन है जो निर्धारित करता है कि कम से कम एक तत्व दिए गए अनुमान से मेल खाता है या नहीं।

ध्यान दें कि यह उत्तर तत्वों को फ़िल्टर करने के पथ के बारे में कोई अनुमान नहीं लगाता है। यदि आप सुरक्षित रूप से कह सकते हैं कि प्रत्येक पथ में, मूल निर्देशिका को आईडी के साथ नामित किया गया है, तो प्रदर्शन कारण के लिए आपको निश्चित रूप से @ बोहेमियन उत्तर के साथ जाना चाहिए।

+1

'p.toString()। (आईडी) 'का अर्थ है" 54 "। (" 4 ")' या 543 " .contains ("4") 'मुझे संदेह है कि यह ओपी के इरादों से मेल खाता है। – Holger

+0

@ होल्गर मैं सहमत हूं, इसलिए मैंने कहा कि वह कुछ बेहतर कार्यान्वित करना चाहता है (जैसे फ़ाइल नाम की शुरुआत से मिलान करना)। – Tunaki

1

तो जैसा:

List removeMissing(List l1, List l2) { 
    List ret = l1.stream() 
     .filter(o -> l2.contains(o)) //Keep if object o satisfies the condition "l2 contains a reference to this object" 
     .collect(Collectors.toList()); 
    return ret; 
} 
0

यदि आपकी फ़ाइल नाम संरचना स्थिर है, तो मैं नंबर निकालने के लिए पहले एक रेगेक्स का उपयोग करता हूं, और फिर यह जांच करेगा कि यह वांछित आईडी में से है या नहीं।

final Set<String> acceptedIds = ... 
// Matches the number of the file, concluded with the underscore 
final Pattern extractor = Pattern.compile("\.*(?<number>\d+)_") 
filePaths.stream().filter(path -> { 
    final Matcher m = extractor 
     .matcher(path.getFileName().toString()); 
    m.find(); 
    return acceptedIds.contains(m.group("number")); 
}) 
... 
संबंधित मुद्दे