Django - liczenie goli powyzej/ponizej 0.5 1.5 2.5

0

Witam, mam taki problem, chce policzyć ile meczy jest powyżej 0.5 1.5 2.5 gola i poniżej 0.5 1.5 2.5 gola. Dane pobieram z API i mam taki kod:

def get_match_data(request):

    api_key = ""

    if request.method == "POST":
        league_id = request.POST.get('league_id')
    else:
        league_id = 148
    if request.method == "POST":
        from_date = request.POST.get('from_date')
    else:
        from_date = datetime.datetime.now().date()
    if request.method == "POST":
        to_date = request.POST.get('to_date')
    else:
        to_date = datetime.datetime.now().date()



    url = "https://apiv2.apifootball.com/"

    querystring = {"action": "get_events", 'league_id': league_id,
                   "from": from_date, "to": to_date, "APIkey": api_key}

    load = ""

    r = requests.request("GET", url, data=load, params=querystring)
    r = r.json()
    length = len(r)

    match_data = []
    match_error = {}


    try:
        for i in range(length):
            match = {
                'match_id': r[i]['match_id'],
                "match_status": r[i]['match_status'],
                'match_date': r[i]['match_date'],
                'match_time':  r[i]['match_time'],
                'home_team': r[i]['match_hometeam_name'],
                'home_team_score': r[i]['match_hometeam_score'],
                'away_team': r[i]['match_awayteam_name'],
                'away_team_score': r[i]['match_awayteam_score'],
                'team_home_badge': r[i]['team_home_badge'],
                'team_away_badge': r[i]['team_away_badge'],
                'score_fulltime': int(r[i]['match_hometeam_score']) + int(r[i]['match_awayteam_score']),
                'score_over05': int(r[i]['match_hometeam_score']) + int(r[i]['match_awayteam_score']) > 0.5,
                'score_over15': int(r[i]['match_hometeam_score']) + int(r[i]['match_awayteam_score']) > 1.5,
                "score_over25": int(r[i]['match_hometeam_score']) + int(r[i]['match_awayteam_score']) > 2.5,
                "score_below05":int(r[i]['match_hometeam_score']) + int(r[i]['match_awayteam_score']) < 0.5,
                "score_below15":int(r[i]['match_hometeam_score']) + int(r[i]['match_awayteam_score']) < 1.5,
                "score_below25":int(r[i]['match_hometeam_score']) + int(r[i]['match_awayteam_score']) < 2.5,
            }

            match_data.append(match)

    except:
        match_error = {
            'message': r['message']
        }
    return render(request, 'footballstats/mecz.html', context={'match_data': match_data, 'match_error': match_error})

I moje pytanie jest następujące jak to teraz najlepiej zrobić?

0

Pokaż jak wygląda to match_data.

2

Biorac pod uwage ze match_data jest tablica dziennikow o tej samej strukturze mozna zrobic tak (pewnie mozna krocej, ale dziala (zlicza, autor musi przetestowac) :P)

match_data = [{'score_over05':1,  "score_over25":2}, {"score_below15":1,  "score_below05":2}, {"score_below25":1,  'score_over05':2}]
wsio = {}
for x in match_data:
    for k,v in x.items():
        if k in wsio.keys():
            wsio[k] += v
        elif "score" in k:
            wsio[k] = v
print(wsio)

>> {'score_over05': 3, 'score_over25': 2, 'score_below15': 1, 'score_below05': 2, 'score_below25': 1}

Maly edit z symulacja keyow autora

0

pewnie mozna krocej, ale dziala

Co działa, podaje ilość meczy spełniających warunki?

0
ledi12 napisał(a):

Biorac pod uwage ze match_data jest tablica dziennikow o tej samej strukturze mozna zrobic tak (pewnie mozna krocej, ale dziala (zlicza, autor musi przetestowac) :P)

match_data = [{'score_over05':1,  "score_over25":2}, {"score_below15":1,  "score_below05":2}, {"score_below25":1,  'score_over05':2}]
wsio = {}
for x in match_data:
    for k,v in x.items():
        if k in wsio.keys():
            wsio[k] += v
        elif "score" in k:
            wsio[k] = v
print(wsio)

>> {'score_over05': 3, 'score_over25': 2, 'score_below15': 1, 'score_below05': 2, 'score_below25': 1}

Maly edit z symulacja keyow autora

Okej, wszystko działa, zlicza mi wszystko tak jak powinno w konsoli.
Teraz mam pytanie - pewnie początkujące ale uczę się dopiero, jak przenieść te wyniki do template żeby wyświetliło się na stronie?

1
szymonzz napisał(a):
ledi12 napisał(a):

Biorac pod uwage ze match_data jest tablica dziennikow o tej samej strukturze mozna zrobic tak (pewnie mozna krocej, ale dziala (zlicza, autor musi przetestowac) :P)

match_data = [{'score_over05':1,  "score_over25":2}, {"score_below15":1,  "score_below05":2}, {"score_below25":1,  'score_over05':2}]
wsio = {}
for x in match_data:
    for k,v in x.items():
        if k in wsio.keys():
            wsio[k] += v
        elif "score" in k:
            wsio[k] = v
print(wsio)

>> {'score_over05': 3, 'score_over25': 2, 'score_below15': 1, 'score_below05': 2, 'score_below25': 1}

Maly edit z symulacja keyow autora

Okej, wszystko działa, zlicza mi wszystko tak jak powinno w konsoli.
Teraz mam pytanie - pewnie początkujące ale uczę się dopiero, jak przenieść te wyniki do template żeby wyświetliło się na stronie?

views:

context = {
    "data":match_data
}
return render(request, template, context)

a w template:

{for k,v in data.items()}
0

Ode mnie małe code review :)

Na początek wspomnę tylko, że strasznie nieczytelnie to wszystko wygląda. Zdefiniuj sobie najlepiej dataclass Match z potrzebnymi polami i składaj listę składającą się z tych obiektów Match, zyskasz trochę na czytelności kosztem pamięci (zakładam że nie jest to aspekt krytyczny).

Dodatkowo pytanie - czy nie lepiej w obiekcie trzymać jedno pole w które wrzucisz zliczoną ilość goli? Później złożysz sobie np. listę meczów, których ta ilość goli przekraczała jakąś wartość lub zliczysz ile meczów się załapało do danego kryterium. W takim przypadku jak Ty to robisz logika związana z trzymanymi wartościami w polach jest powielana, co wydaje się dla tego przypadku zbędne.

Dla uproszczenia dam przykład który operuje na prostych obiektach nie zawierających wszystkich pól, których Ty używasz.
Przykładowe obiekty dla pojedynczych meczów, które składasz w pętli:

match1 = {'team_a': 'Arsenal', 'team_b': 'Bayern', 'total_goals': 10}
match2 = {'team_a': 'Internazionale', 'team_b': 'Juventus', 'total_goals': 5}
match3 = {'team_a': 'Borussia', 'team_b': 'Legia', 'total_goals': 12}

matches = [match1, match2, match3]

W takim przypadku aby uzyskać ilość meczów, które spełniają przykładowo kryterium total_goals > 5 robimy:

number_of_matches_over_five_goals = len(list(filter(lambda match: match['total_goals'] > 5, matches)))

Jeśli chcesz otrzymać listę tych meczów, to wystarczy:

matches_over_five_goals = list(filter(lambda match: match['total_goals'] > 5, matches))

Dodatkowo zwracam uwagę na to, że robisz try, except bez żadnego konkretnego Exception. Jakiego konkretnego Exception się spodziewasz? Jak obsłużysz przypadek, jeśli r['message'] rzuci kolejny wyjątek KeyError?

Dodatkowo niepotrzebnie iterujesz używając indeksów.
Zamiast

for i in range(length):
    ...

użyj

for match in r:
    ...

Później zamiast fetchować obiekty po r[i] będziesz mógł po prostu używać match, np:

'match_id': r[i]['match_id']

zastąpisz

'match_id': match['match_id']

Dodatkowo jeśli w twoim iterowalnym r znajduje się wiele obiektów, to zamiast iterować bezpośrednio na nim, możesz sobie z niego zrobić generator:

for match in (i for i in matches):
    ...

Dzięki temu zaoszczędzisz też odrobinę pamięci. To tak tylko na przyszłość gdyby ten aspekt był krytyczny.

Przytoczone wcześniej rozwiązania raczej odradzam jeśli nie chcesz łapać złych nawyków. Mimo że działa, to złożoność obliczeniowa leży i kwiczy. Jako że jesteś początkującym, taka sytuacja może wydawać porządku bo przecież działa, jednak w przyszłości na pierwszej lepszej rekrutacji takie coś może Cię wykluczyć z puli kandydatów.

1 użytkowników online, w tym zalogowanych: 0, gości: 1