मेरे पास एक वस्तु है जो इस तरह दिखने वाले अजगर में एक आयत का प्रतिनिधित्व करती है:

class cords:
    x_start = -1
    x_end = -1
    y_start = -1
    y_end = -1

    def __init__(self, x_start, x_end, y_start, y_end):
        self.x_start = x_start
        self.x_end = x_end
        self.y_start = y_start
        self.y_end = y_end

अब मेरे पास cords नाम की एक सूची है new_cords इस तरह के मूल्यों के साथ:

x_start: 508, x_end: 530, y_start: 843, y_end: 869
x_start: 508, x_end: 530, y_start: 843, y_end: 870
x_start: 401, x_end: 451, y_start: 582, y_end: 620
x_start: 467, x_end: 513, y_start: 583, y_end: 621
x_start: 466, x_end: 512, y_start: 634, y_end: 672
x_start: 533, x_end: 585, y_start: 534, y_end: 561
x_start: 528, x_end: 576, y_start: 583, y_end: 622

मैं समान आयतों को कम करने के लिए new_cords आयतों से हटाना चाहता हूं जो एक दूसरे से 3 की दूरी पर हैं।

मैंने यह लिखा:

for c_out in new_cords:
    for c_in in new_cords:
        if abs(c_out.x_start - c_in.x_start) < 3 or abs(c_out.x_end - c_in.x_end) < 3 or abs(c_out.y_start - c_in.y_start) < 3 or abs(c_out.y_end - c_in.y_end) < 3:
            new_cords.remove(c_out)

लेकिन मुझे अपवाद मिलते हैं क्योंकि यह उन मानों को हटा देता है जो मौजूद नहीं हैं और मुझे सही सूची नहीं मिलती है।

मेरे एल्गोरिदम में क्या गलत है?

संपादित करें: एल्गोरिदम को उनमें से केवल एक को हटाना चाहिए। उदाहरण के लिए, ए और बी करीब हैं, इसलिए हमें ए (या बी) को हटाना चाहिए, लेकिन दोनों को नहीं

1
TheAndoOne 2 मार्च 2020, 13:07

2 जवाब

आपको उस सूची से आइटम नहीं हटाना चाहिए, जिस पर आप पुनरावृति कर रहे हैं। इसके बजाय एक नई सूची बनाएं जिसमें ऐसे आइटम हों जिन्हें नहीं हटाया जाना चाहिए:

new_cords = [ c_out for c_out in new_cords for c_in in new_cords if not (abs(c_out.x_start - c_in.x_start) < 3 or abs(c_out.x_end - c_in.x_end) < 3 or abs(c_out.y_start - c_in.y_start) < 3 or abs(c_out.y_end - c_in.y_end) < 3) ]

(कृपया अपनी स्थिति की उपेक्षा पर ध्यान दें)

1
Błotosmętek 2 मार्च 2020, 13:17
एक साइड टिप्पणी: यदि स्थिति को फ़ंक्शन के रूप में परिभाषित किया गया था तो यह कोड अधिक पठनीय होगा।
 – 
Błotosmętek
2 मार्च 2020, 13:24

जो कार्य मैं समझता हूं वह सूची में से कुछ आयतों को हटाना है ताकि शेष आयत बहुत समान न हों।

बचे हुए आयतों की संख्या को अधिकतम करना वास्तव में एक ग्राफ़ सिद्धांत समस्या है।

निम्नलिखित समाधान इष्टतम नहीं है, लेकिन शेष संख्या को यथासंभव बड़ा बना सकता है:

def remove_similar(cord_list):
    is_similar = (
        lambda n1, n2: abs(n1.x_start - n2.x_start) < 3
        or abs(n1.x_end - n2.x_end) < 3
        or abs(n1.y_start - n2.y_start) < 3
        or abs(n1.y_end - n2.y_end) < 3
    )

    res = []
    while cord_list:
        c_in = cord_list.pop()
        cord_list = [n for n in cord_list if not is_similar(n, c_in)]
        res.append(c_in)
    return res

यह सुनिश्चित करने के लिए कि कोड मान्य है, मैं 100 आयतों की सूची में 1000 परीक्षण चलाता हूं:

import numpy as np


def build_test(size):
    return [cords(*np.random.randint(0, 1000, 4).tolist()) for _ in range(size)]


def check(cord_list):
    assert not any(
        [n1 != n2 and too_close(n1, n2) for n1 in cord_list for n2 in cord_list]
    )
    return len(cord_list)


res_size_mean = 0
for _ in range(1000):
    new_cords = build_test(100)
    res = remove_similar(new_cords)
    res_size_mean += check(res) / 1000

print(res_size_mean)
# 53.591999999999736
2
loopy 3 मार्च 2020, 09:19
यह लगभग अच्छा है। लेकिन, अगर मेरे पास एक आयत है जिसके पास कोई अन्य आयत नहीं है, तो इसे if c_out == c_in: continue शर्त के कारण हटा दिया जाएगा
 – 
TheAndoOne
2 मार्च 2020, 18:48
मैंने समस्या की समीक्षा की और एक नया समाधान प्रस्तावित किया। नए कोड का परीक्षण किया गया है।
 – 
loopy
3 मार्च 2020, 09:22