Работа с абстрактными фильтрами (понимание списка): объединение двух фильтров - PullRequest
4 голосов
/ 18 декабря 2011

Короткий и острый: Учитывая два логических выражения, как проще всего вычислить уравнение их пересечения в языке, подобном Lua?

Venn Diagram(Красный = Фильтр 1, Синий = Фильтр 2, Фиолетовый = Область пересечения)

Длинный и скорбящий:

  • Фильтр A: object.ID < 300

  • Фильтр B : object.ID < 600

Фильтр A это подмножество из Фильтр B , то есть: Фильтр B будет содержать все, что соответствует Фильтр A , плюс 0 или более объектов,На диаграмме Венна Фильтр A будет находиться внутри Фильтр B .

Как вычислить уравнение площади пересечения?

Aболее сложный пример:

  • Фильтр X : object.Col == 'GREEN' and (object.ID == 2 or object.ID == 64 or object.ID > 9001)
  • Фильтр Y : (object.Col == 'RED' or object.Col == 'GREEN') and (object.ID == 3 or object.ID > 22)

Фильтр A пересекается с Фильтр B .На диаграмме Венна они будут перекрываться.Уравнение для перекрывающейся области будет иметь вид:object.Col == 'GREEN' and (object.ID == 64 or object.ID > 9001)

Как будет рассчитываться это уравнение на языке, таком как Python или Haskell?

Я бы хотел в конечном итоге сделать это на Lua, но если бы Python, Haskell или другой язык предоставляли функциональностьЯ мог бы посмотреть на исходный код и преобразовать его.

Вот как я представляю фильтры в Lua:

filter = DataFilter(
    {"and",
        {"or",
            {"==", "Col", "RED"},
            {"==", "Col", "GREEN"},
        },
        {"or",
            {"==", "ID", 3},
            {">" , "ID", 22},
        },
    }
)

Пожалуйста, укажите мне правильное направление.

Ответы [ 3 ]

3 голосов
/ 18 декабря 2011

Дикая догадка: приведите «Фильтры» в дизъюнктивную нормальную форму и уменьшите их, используя соответствующие методы (x == 8 содержится в x> 5).

2 голосов
/ 18 декабря 2011

Это каким-то образом вы можете достичь этого.Код с комментариями поможет вам понять подход

#Create a Class Foo with attributes id and col
class Foo:
    def __init__(this,ID,COL):
        this.id=ID
        this.col=COL



#Dataset
data=["VIOLET","INDIGO","BLUE","GREEN","YELLOW","ORANGE","RED"]
ObjList=[Foo(random.randint(1,70),random.choice(data)) for i in xrange(1,10000)]

#Create the Filter Functions
def FilterX(obj):
    return obj.col == 'GREEN'  and (obj.id == 2 or obj.id == 64 or obj.id > 9001)

def FilterY(obj):
    return (obj.col == 'RED' or obj.col == 'GREEN') and (obj.id == 3  or obj.id > 22)

def FilterZ(obj):
    return obj.col == 'GREEN'  and (obj.id > 50)

#Create a list of filter functions
filters=[FilterX,FilterY,FilterZ]

#Create a set result (that will hold the intersected data) and assign the result of
#applying the First Filter on ObjList
result=set(filter(filters[0],ObjList))

#For the Rest of the filter's apply them on the ObjList, and then intersect
#the resultant set with the result
for s in (set(filter(foo,ObjList)) for foo in filters[1:]):
    result=result.intersection(s)

#Finally Display the result
[(obj.id,obj.col) for obj in result]
1 голос
/ 18 декабря 2011

Я не знаю, упустил ли я важный момент здесь. Кажется, что ваши фильтры просто возвращают логическое значение в зависимости от качества «объекта». Почему бы вам просто не использовать обычные "и" и "или" s и функции для их составления?

Вот как я бы сделал ваши фильтры в Lua:

function filterX(object)
  return object.Col == 'GREEN' and 
    (object.ID == 2 or object.ID == 64 or object.ID > 9001)
end

function filterY(object)
   return (object.Col == 'RED' or object.Col == 'GREEN') and 
     (object.ID == 3 or object.ID > 22)
end

Вы можете определить «объединение» или «пересечение» этих фильтров с помощью этих дополнительных функций:

function union(f,g)
  return function(...)
    return f(...) or g(...)
  end
end

function intersection(f,g)
  return function(...)
    return f(...) and g(...)
  end
end

А вот как ты сочиняешь:

union(filterX, filterY)(object) -- returns true or false
intersection(filterX, filterY)(object) -- true or false

Или, если вы хотите использовать их часто:

filterXorY = union(filterX, filterY)
filterXandY = intersection(filterX, filterY)

filterXorY(object) -- true or false
filterXandY(object) -- true or false

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...