简体   繁体   中英

Can a JS object's properties be overwritten in a loop?

I have this piece of code that combines the output of two APIs keeping only the data I require. I am aware this may not be the most efficient way of doing this, the biggest factor to that is why do I not just use the odds API by itself, the answer being that the matches API has historical data and the odds do not.

What's confusing me is why after seeing all the output logs does matchesAndOdds only contain the away teams odds and bot the odds for the home team.

Could someone tell me the mistake I've made?

I'm thinking that the properties of the odds object are somehow being overwritten?

(Note: the arrays matches and odds do contain more objects in reality, I've cut them down so the snippets not too long)

 const odds = [ { "id": "dd7aff0584aee475b4d67ab83655f379", "sport_key": "aussierules_afl", "sport_title": "AFL", "commence_time": "2022-06-30T09:20:00Z", "home_team": "Brisbane Lions", "away_team": "Western Bulldogs", "bookmakers": [ { "key": "unibet", "title": "Unibet", "last_update": "2022-06-29T12:14:33Z", "markets": [ { "key": "h2h", "outcomes": [ { "name": "Brisbane Lions", "price": 1.36 }, { "name": "Western Bulldogs", "price": 3.15 } ] } ] } ] } ] const matches = [ { gametime: "2022-06-30T09:20:00.000Z", home_team: 'Brisbane Lions', away_team: 'Western Bulldogs', ground: 'Gabba', home_points: 108, away_points: 67, selected: null } ] // Translation dictionary for the two APIs // ff = matches and oa = odds const ffToOa = { "Western Bulldogs": "Western Bulldogs", "Brisbane Lions": "Brisbane Lions", "St Kilda": "St Kilda Saints", "Carlton": "Carlton Blues", "Sydney": "Sydney Swans", "Essendon": "Essendon Bombers", // ? Hopefully this will hanle when and if // ? the Demons change their name back from Naarm "Melbourne": "Melbourne Demons", "Naarm": "Melbourne Demons", "Adelaide": "Adelaide Crows", "North Melbourne": "North Melbourne Kangaroos", "Geelong": "Geelong Cats", "Collingwood": "Collingwood Magpies", "Gold Coast": "Gold Coast Suns", "West Coast": "West Coast Eagles", "Richmond": "Richmond Tigers", "Hawthorn": "Hawthorn Hawks", "GWS": "Greater Western Sydney Giants", "Port Adelaide": "Port Adelaide Power", "Fremantle": "Fremantle Dockers" } let matchesAndOdds = [...matches]; matches.forEach((match, i) => { matchesAndOdds[i].odds = {}; odds.forEach(odd => { // odds.data.forEach(odd => { if (odd.home_team === ffToOa[match.home_team] && odd.away_team === ffToOa[match.away_team]) { odd.bookmakers.forEach(bookmaker => { bookmaker.markets[0].outcomes.forEach(outcome => { matchesAndOdds[i].odds[bookmaker.title] = {}; console.log(`${i}. if (${outcome.name} === ${odd.home_team})`); console.log(`${i}. if (${outcome.name} === ${odd.away_team})`); console.log("-----------------------------------------"); if (outcome.name === odd.home_team) { console.log(`${i}. home ${bookmaker.title} ${outcome.price}`); matchesAndOdds[i].odds[bookmaker.title].home = outcome.price; console.log(matchesAndOdds[i].odds[bookmaker.title].home); } else if (outcome.name === odd.away_team) { console.log(`${i}. away ${bookmaker.title} ${outcome.price}`); matchesAndOdds[i].odds[bookmaker.title].away = outcome.price; console.log(matchesAndOdds[i].odds[bookmaker.title].away); } }) }) } }) }) console.log(matchesAndOdds)

The problem is here:

    bookmaker.markets[0].outcomes.forEach(outcome => {
      matchesAndOdds[i].odds[bookmaker.title] = {};

This resets the odds[bookmaker.title] object in every iteration over outcomes . This will destroy the results from the previous iteration of this loop. This initialisation should happen before the loop:

    matchesAndOdds[i].odds[bookmaker.title] = {};
    bookmaker.markets[0].outcomes.forEach(outcome => {

You can actually make the process with a bit "nicer" code:

 const odds =[{"id": "dd7aff0584aee475b4d67ab83655f379","sport_key": "aussierules_afl","sport_title": "AFL","commence_time": "2022-06-30T09:20:00Z","home_team": "Brisbane Lions","away_team": "Western Bulldogs","bookmakers": [{"key": "unibet","title": "Unibet","last_update": "2022-06-29T12:14:33Z","markets": [{"key": "h2h","outcomes": [{"name": "Brisbane Lions","price": 1.36},{"name": "Western Bulldogs","price": 3.15}]}]}]}] const matches =[{gametime: "2022-06-30T09:20:00.000Z",home_team: 'Brisbane Lions',away_team: 'Western Bulldogs',ground: 'Gabba',home_points: 108,away_points: 67,selected: null}] const ffToOa = {"Western Bulldogs": "Western Bulldogs","Brisbane Lions": "Brisbane Lions","St Kilda": "St Kilda Saints","Carlton": "Carlton Blues","Sydney": "Sydney Swans","Essendon": "Essendon Bombers","Melbourne": "Melbourne Demons","Naarm": "Melbourne Demons","Adelaide": "Adelaide Crows","North Melbourne": "North Melbourne Kangaroos","Geelong": "Geelong Cats","Collingwood": "Collingwood Magpies","Gold Coast": "Gold Coast Suns","West Coast": "West Coast Eagles","Richmond": "Richmond Tigers","Hawthorn": "Hawthorn Hawks","GWS": "Greater Western Sydney Giants","Port Adelaide": "Port Adelaide Power","Fremantle": "Fremantle Dockers"} const matchesAndOdds = matches.map(match => { const {home_team, bookmakers} = odds.find(odd => odd.home_team === ffToOa[match.home_team] && odd.away_team === ffToOa[match.away_team] ) ?? {}; return home_team ? { ...match, odds: Object.fromEntries(bookmakers.map(({title, markets: [{outcomes}]}) => [ title, Object.fromEntries(outcomes.map(outcome => [outcome.name === home_team ? "home" : "away", outcome.price] )) ])) } : match; }); console.log(matchesAndOdds);

As indicated in another answer, the problem was in overwritting the output variable for each outcome iteration.

You indicated that you thought it might not be the most efficient way, and indeed there might be, or at least the code could be more concise. Here, rather than duplicating arrays up front, I'm using map and reduce to transform each element as encountered.

 const odds = [ { "id": "dd7aff0584aee475b4d67ab83655f379", "sport_key": "aussierules_afl", "sport_title": "AFL", "commence_time": "2022-06-30T09:20:00Z", "home_team": "Brisbane Lions", "away_team": "Western Bulldogs", "bookmakers": [ { "key": "unibet", "title": "Unibet", "last_update": "2022-06-29T12:14:33Z", "markets": [ { "key": "h2h", "outcomes": [ { "name": "Brisbane Lions", "price": 1.36 }, { "name": "Western Bulldogs", "price": 3.15 } ] } ] } ] } ] const matches = [ { gametime: "2022-06-30T09:20:00.000Z", home_team: 'Brisbane Lions', away_team: 'Western Bulldogs', ground: 'Gabba', home_points: 108, away_points: 67, selected: null } ] // Translation dictionary for the two APIs // ff = matches and oa = odds const ffToOa = { "Western Bulldogs": "Western Bulldogs", "Brisbane Lions": "Brisbane Lions", "St Kilda": "St Kilda Saints", "Carlton": "Carlton Blues", "Sydney": "Sydney Swans", "Essendon": "Essendon Bombers", // ? Hopefully this will hanle when and if // ? the Demons change their name back from Naarm "Melbourne": "Melbourne Demons", "Naarm": "Melbourne Demons", "Adelaide": "Adelaide Crows", "North Melbourne": "North Melbourne Kangaroos", "Geelong": "Geelong Cats", "Collingwood": "Collingwood Magpies", "Gold Coast": "Gold Coast Suns", "West Coast": "West Coast Eagles", "Richmond": "Richmond Tigers", "Hawthorn": "Hawthorn Hawks", "GWS": "Greater Western Sydney Giants", "Port Adelaide": "Port Adelaide Power", "Fremantle": "Fremantle Dockers" } const matchesAndOdds = matches.map(match => { const odd = odds.find(item => { return item.home_team === ffToOa[match.home_team] && item.away_team === ffToOa[match.away_team] }) if (odd === undefined) { return match } return { ...match, odds: odd.bookmakers.reduce((bookieOdds, bookmaker) => { return { ...bookieOdds, [bookmaker.title]: bookmaker.markets[0].outcomes.reduce((bookie, outcome) => { return { home: outcome.name === odd.home_team ? outcome.price : bookie.home, away: outcome.name === odd.away_team ? outcome.price : bookie.away, } }, {}) } }, {}) } }) console.log(matchesAndOdds)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM