문제

이것은 부분은 알고리즘-논문(그것을 어떻게),부분 구현 질문(그것을 어떻게 최고!).나는 작업을 장고,그래서 저는 생각을 공유합니다.

파이썬에서,그것은 언급 할 가치가있는 이 문제는 약간과 관련된 는 방법-do-i-사용-파-itertoolsgroupby.

당신은 주어진 두 가지 장고의 모델 파생된 클래스:

from django.db import models

class Car(models.Model):
    mods = models.ManyToManyField(Representative)

from django.db import models

class Mods(models.Model):
   ...

어떻게 하나의 목록을 얻을 차룹으로 자동차와 일반적인 설정의 개조 사용할 수 있습니까?

I.e.내가 원하는 클래스 likeso:

Cars_by_common_mods = [ 
  { mods: { 'a' }, cars: { 'W1', 'W2' } },
  { mods: { 'a', 'b' }, cars: { 'X1', 'X2', 'X3' }, },
  { mods: { 'b' }, cars: { 'Y1', 'Y2' } },
  { mods: { 'a', 'b', 'c' }, cars: { 'Z1' } },
]

나는 생각하고 다음과 같습니다.

def cars_by_common_mods():
  cars = Cars.objects.all()

  mod_list = []      

  for car in cars:
    mod_list.append( { 'car': car, 'mods': list(car.mods.all()) } 

  ret = []

  for key, mods_group in groupby(list(mods), lambda x: set(x.mods)):
    ret.append(mods_group)

  return ret

그러나,작동하지 않기 때문에(아마도 다른 이유 중)groupby 하지 않는 것 같은 그룹에 의해 개조합니다.나는 생각 mod_list 정리되어야 할 작업 groupby.모든 말을 저는 확신이 무언가가 간단하고 우아한 거기는 것이 모두 깨달음이 빛나.

환호 및 감사합니다!

도움이 되었습니까?

해결책

목록을 먼저 정렬해 보셨습니까? 많은 데이터베이스 히트가 있지만 제안한 알고리즘은 작동해야합니다.

import itertools

cars = [
    {'car': 'X2', 'mods': [1,2]},
    {'car': 'Y2', 'mods': [2]},
    {'car': 'W2', 'mods': [1]},
    {'car': 'X1', 'mods': [1,2]},
    {'car': 'W1', 'mods': [1]},
    {'car': 'Y1', 'mods': [2]},
    {'car': 'Z1', 'mods': [1,2,3]},
    {'car': 'X3', 'mods': [1,2]},
]

cars.sort(key=lambda car: car['mods'])

cars_by_common_mods = {}
for k, g in itertools.groupby(cars, lambda car: car['mods']):
    cars_by_common_mods[frozenset(k)] = [car['car'] for car in g]

print cars_by_common_mods

이제 그 질문에 대해 :

import collections
import itertools
from operator import itemgetter

from django.db import connection

cursor = connection.cursor()
cursor.execute('SELECT car_id, mod_id FROM someapp_car_mod ORDER BY 1, 2')
cars = collections.defaultdict(list)
for row in cursor.fetchall():
    cars[row[0]].append(row[1])

# Here's one I prepared earlier, which emulates the sample data we've been working
# with so far, but using the car id instead of the previous string.
cars = {
    1: [1,2],
    2: [2],
    3: [1],
    4: [1,2],
    5: [1],
    6: [2],
    7: [1,2,3],
    8: [1,2],
}

sorted_cars = sorted(cars.iteritems(), key=itemgetter(1))
cars_by_common_mods = []
for k, g in itertools.groupby(sorted_cars, key=itemgetter(1)):
    cars_by_common_mods.append({'mods': k, 'cars': map(itemgetter(0), g)})

print cars_by_common_mods

# Which, for the sample data gives me (reformatted by hand for clarity)
[{'cars': [3, 5],    'mods': [1]},
 {'cars': [1, 4, 8], 'mods': [1, 2]},
 {'cars': [7],       'mods': [1, 2, 3]},
 {'cars': [2, 6],    'mods': [2]}]

이제 자동차 ID 및 모드 ID 목록을 얻었으므로 작업 할 완전한 개체가 필요한 경우 각 모델에 대한 전체 목록을 얻고 조회를 만들 수 있도록 각각에 대해 단일 쿼리를 할 수 있습니다. dict 그것들을 위해, 그들의 ID에 의해 키를 뿌린다. 그러면 나는 밥이 당신의 속담의 아버지의 형제라고 믿는다.

다른 팁

확인하다 다시 그룹. 템플릿에만 해당되지만 이런 종류의 분류는 어쨌든 프레젠테이션 계층에 속한 것 같습니다.

여기에는 몇 가지 문제가 있습니다.

GroupBy에 전화하기 전에 목록을 정렬하지 않았으며 이것이 필요합니다. 에서 itertools 문서:

일반적으로 반복적 인 것은 이미 동일한 키 기능에 정렬되어야합니다.

그런 다음 GroupBy가 반환 한 목록을 복제하지 않습니다. 다시, 문서화는 다음과 같습니다.

반환 된 그룹 자체는 그 자체가 groupby ()와 기본 반복을 공유하는 반복자입니다. 소스가 공유되기 때문에 GroupBY 객체가 발전되면 이전 그룹이 더 이상 보이지 않습니다. 따라서 해당 데이터가 나중에 필요한 경우 목록으로 저장해야합니다.

groups = []
uniquekeys = []
for k, g in groupby(data, keyfunc):
    groups.append(list(g))      # Store group iterator as a list
    uniquekeys.append(k)

그리고 마지막 실수는 세트를 키로 사용하는 것입니다. 그들은 여기서 일하지 않습니다. 빠른 수정은 정렬 된 튜플로 캐스팅하는 것입니다 (더 나은 솔루션이있을 수 있지만 지금은 생각할 수는 없습니다).

따라서 예에서 마지막 부분은 다음과 같아야합니다.

sortMethod = lambda x: tuple(sorted(set(x.mods)))
sortedMods = sorted(list(mods), key=sortMethod)
for key, mods_group in groupby(sortedMods, sortMethod):
    ret.append(list(mods_group))

성능이 우려되는 경우 (예 : 페이지의 많은 자동차 또는 교통량이 많은 사이트), 비정규 화 합리적이며 부작용으로 문제를 단순화합니다.

다수의 관계를 제거하는 것은 약간 까다로울 수 있습니다. 나는 아직 그러한 코드 예제를 다루지 않았습니다.

당신은 도움이 대답.나는 멀리에서 이 문제를 해결합니다.'최적의 솔루션은 여전히 회피하지만,나는 어떤 생각입니다.

나도 언급해야한다는 통계 데이터의 설정과 작업에 어떤 영향을 주었을까요.75%에서의 사례 중 하나가 될 것입니다.에서 24%의 경우,두.에서 1%의 경우가,또는 세 이상입니다.에 대한 모든 모드가 있는 적어도 하나의 독특한 차지만,모드에 적용할 수 있는 수많은 자동차입니다.

제로 간주했다(하지만 구현되지 않)같은 것-그래서:

class ModSet(models.Model):
  mods = models.ManyToManyField(Mod)

변 자동차

class Car(models.Model):
  modset = models.ForeignKey(ModSet)

그것의 사소한 그룹입니다.modset:내가 사용할 수있는,재편성에 의해 제안으로 하비에르,예를 들어.그것은 보인다 간단하고 합리적인 우아한 해결책;생각은 많이 주시면 감사하겠습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top