0

I'm trying to create a quiz program but at the moment I have a list for each category. I would like to use the same list and just call the categories I want in each quiz.

private void LoadQuestions()
        {
            Question q1 = new Question
            {
                NameOfQuestion = "Vem är världens bästa golfspelare?",
                Options = new List<string>() { "Tiger Woods", "Matt Kuchar", "S.H. Kim", "Adam Scott" },
                Answer = "Tiger Woods",
                Category = "Golf"
            };

            Question q2 = new Question
            {
                NameOfQuestion = "Vad heter Rory i efternamn?",
                Options = new List<string>() { "Svensson", "Mcilroy", "Eriksson", "Smith" },
                Answer = "Mcilroy",
                Category = "Golf"
            };

            Question q3 = new Question
            {
                NameOfQuestion = "Hur många golfhål spelar man under en tävling?",
                Options = new List<string>() { "18", "26", "72", "180" },
                Answer = "72",
                Category = "Golf"
            };

            Question q4 = new Question
            {
                NameOfQuestion = "Vilken bana spelas Masters på?",
                Options = new List<string>() { "TPC Sawgrass", "Agusta", "Halmstad GK", "The Country Club" },
                Answer = "Agusta",
                Category = "Golf"
            };

            Question q5 = new Question
            {
                NameOfQuestion = "Vad har Gustav i HCP?",
                Options = new List<string>() { "Alldeles för högt", "Alldeles för lågt", "Han är bäst", "Han är sämst" },
                Answer = "Han är sämst",
                Category = "Golf"
            };

            Question q6 = new Question
            {
                NameOfQuestion = "Hur många spelare är på isen samtidigt?",
                Options = new List<string>() { "8", "10", "6", "12" },
                Answer = "12",
                Category = "Hockey"
            };

            Question q7 = new Question
            {
                NameOfQuestion = "Hur lång är en hockeymatch?",
                Options = new List<string>() { "40 minuter", "60 minuter", "90 minuter", "45 minuter" },
                Answer = "60 minuter",
                Category = "Hockey"
            };

            Question q8 = new Question
            {
                NameOfQuestion = "Hur många poäng får ett lag om de vinner i övertid?",
                Options = new List<string>() { "3", "4", "2", "1" },
                Answer = "2",
                Category = "Hockey"
            };

            Question q9 = new Question
            {
                NameOfQuestion = "Vilken färg har en hockeypuck?",
                Options = new List<string>() { "Mörkblå", "Svart", "Grå", "Svart & vit" },
                Answer = "Svart",
                Category = "Hockey"
            };

            Question q10 = new Question
            {
                NameOfQuestion = "Vad kallas det när det står 40-40 i tennis?",
                Options = new List<string>() { "Even", "All square", "Deuce", "Even Steven" },
                Answer = "Deuce",
                Category = "Tennis"
            };

            Question q11 = new Question
            {
                NameOfQuestion = "Vad heter den kända svensken som tog 11 grand slam-segrar?",
                Options = new List<string>() { "Björn Borg", "Stefan Edberg", "Gustav Eriksson", "Mats Wilander" },
                Answer = "Björn Borg",
                Category = "Tennis"
            };

            Question q12 = new Question
            {
                NameOfQuestion = "Vart föddes den kända tennisspelaren Andy Murray?",
                Options = new List<string>() { "Wales", "England", "Scotland", "Ireland" },
                Answer = "Scotland",
                Category = "Tennis"
            };

            Question q13 = new Question
            {
                NameOfQuestion = "Vad kallas det kända mästerskap som spelas i England varje år?",
                Options = new List<string>() { "Wimbledon", "Offerthon", "English Tennis Cup", "London Tennis Championship" },
                Answer = "Wimbledon",
                Category = "Tennis"
            };

            Question q14 = new Question
            {
                NameOfQuestion = "Avsluta meningen: Game, Set &    ",
                Options = new List<string>() { "Victory", "Relax", "Time to make your bet", "Match" },
                Answer = "Match",
                Category = "Tennis"
            };

            Question q15 = new Question
            {
                NameOfQuestion = "Vilken låt är den mest strömmade på spotify?",
                Options = new List<string>() { "The Weeknd - Blinding Lights", "Ed Sheeran - Shape Of You", "Tones And I - Dance Monkey", "Post Malone - Rockstar" },
                Answer = "The Weeknd - Blinding Lights",
                Category = "Music"
            };

            Question q16 = new Question
            {
                NameOfQuestion = "Vilket band har gjort låten: Smoke on the water?",
                Options = new List<string>() { "Europe", "Iron Maiden", "Rolling Stones", "Deep Purple" },
                Answer = "Deep Purple",
                Category = "Music"
            };

            Question q17 = new Question
            {
                NameOfQuestion = "Vilken är Avicii's mest streamade låt på spotify?",
                Options = new List<string>() { "The Nights", "The Days", "Wake Me Up", "Without you" },
                Answer = "Wake Me Up",
                Category = "Music"
            };

            Question q18 = new Question
            {
                NameOfQuestion = "The Beatles är otroligt känt band med bandmedlemmar som John Lennon, Ringo Starr och Paul McCartney. Vad heter den fjärde medlemmen?",
                Options = new List<string>() { "George Harisson", "Dean Smith", "George Davidson", "Terry McDavid" },
                Answer = "George Harisson",
                Category = "Music"
            };

            Question q19 = new Question
            {
                NameOfQuestion = "Elvis Presley performed the song Hound dog. Please continue the lyrics to the song: You ain't nothing but a hound dog:",
                Options = new List<string>() { "Party'n all the time", "Lying all the time", "Crying all the time", "Smiling everytime" },
                Answer = "Crying all the time",
                Category = "Music"
            };

            Question q20 = new Question
            {
                NameOfQuestion = "Who performed the song: Like a virgin?",
                Options = new List<string>() { "Madonna", "Rihanna", "Britney Spears", "Cher" },
                Answer = "Madonna",
                Category = "Music"
            };

            Question q21 = new Question
            {
                NameOfQuestion = "Walter White är en högskolelärare som börjar att tillverka droger. Vad heter denna serie?",
                Options = new List<string>() { "Game Of Thrones", "Drugs & Teach", "Breaking Bad", "Cocaine & Clementine" },
                Answer = "Breaking Bad",
                Category = "Film & TV-Serie"
            };

            Question q22 = new Question
            {
                NameOfQuestion = "I sagan om ringen finns det en liten hobbit som blivit förvriden av mörkret. Han mumlar ofta: my precious... Vad heter denna karaktär?",
                Options = new List<string>() { "Smeagol", "Reagol", "Chero", "Mearo" },
                Answer = "Smeagol",
                Category = "Film & TV-Serie"
            };

            Question q23 = new Question
            {
                NameOfQuestion = "Vilken film har högst betyg på rating-sidan IMDB?",
                Options = new List<string>() { "Gudfadern", "The Dark Knight", "Nyckeln till frihet", "Schindler's List" },
                Answer = "Nyckeln till frihet",
                Category = "Film & TV-Serie"
            };

            Question q24 = new Question
            {
                NameOfQuestion = "Vilken TV-serie har högst betyg på rating-sidan IMDB?",
                Options = new List<string>() { "Planet Earth", "Planet Earth II", "Breaking Bad", "Band of Brothers" },
                Answer = "Planet Earth II",
                Category = "Film & TV-Serie"
            };

            Question q25 = new Question
            {
                NameOfQuestion = "Vad heter det svenska företaget som fram till 2012 tillverkade bilar? De kanske är mest kända för sina flygplan.",
                Options = new List<string>() { "Volvo", "Audi", "Saab", "Gripen" },
                Answer = "Saab",
                Category = "Bilar"
            };

            Question q26 = new Question
            {
                NameOfQuestion = "Vad heter företaget från Ängelholm som tillverkar världens snabbaste bilar?",
                Options = new List<string>() { "Hyundai", "Roendi", "Polestar", "Koenigsegg" },
                Answer = "Koenigsegg",
                Category = "Bilar"
            };

            Question q27 = new Question
            {
                NameOfQuestion = "Volvo är ett stort bilföretag som är baserat i Göteborg, Sverige. Men vad betyder volvo på latin?",
                Options = new List<string>() { "Säkerhet", "Jag rullar", "Snabb och kompakt", "Säkert rullande" },
                Answer = "Jag rullar",
                Category = "Bilar"
            };

            Question q28 = new Question
            {
                NameOfQuestion = "Vad heter det kända Italienska bilmärket som är kända för sin röda färg?",
                Options = new List<string>() { "Lamborghini", "Rolls Royce", "Audi", "Ferrari" },
                Answer = "Ferrari",
                Category = "Bilar"
            };

            Question q29 = new Question
            {
                NameOfQuestion = "Vilket är världens mest sålda TV-spel?",
                Options = new List<string>() { "Counter Strike: Global Offensive", "Minecraft", "World Of Warcraft", "Grand Theft Auto V" },
                Answer = "Minecraft",
                Category = "TV-Spel"
            };

            Question q30 = new Question
            {
                NameOfQuestion = "Vad heter Mario's bror?",
                Options = new List<string>() { "Bowser", "Toad", "Luigi", "Yoshi" },
                Answer = "Luigi",
                Category = "TV-Spel"
            };

            Question q31 = new Question
            {
                NameOfQuestion = "Vilken svensk skapade Minecraft?",
                Options = new List<string>() { "Markus Persson", "Daniel Ek", "Joakim Larsson", "Max Pettersson" },
                Answer = "Markus Persson",
                Category = "TV-Spel"
            };

            Question q32 = new Question
            {
                NameOfQuestion = "Battle Royale är ett populärt läge. Det innebär att man möter andra lag och laget som är kvar sist vinner. Vilket är det populäraste Battle Royale Spelet?",
                Options = new List<string>() { "Fortnite", "Apex Legends", "PUBG: Battlegrounds", "Call Of Duty: Warzone" },
                Answer = "PUBG: Battlegrounds",
                Category = "TV-Spel"
            };

            Questions.AddRange(new List<Question> { q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21, q22, q23, q24, q25, q26, q27, q28, q29, q30, q31, q32 });
        }

This is the list I would like to use, but I'm not sure how to only call the golf questions or how to only call the movies questions etc.

Right now I have a list for each category, so I'm calling the lists in blazor like this:

        @if (questionIndex5 < QuestionsGolf.Count)
        {
                <div class="app-title">
                    @QuestionsGolf[questionIndex5].Category
                </div>
                <div class="quiz-header">
                    @QuestionsGolf[questionIndex5].NameOfQuestion
                </div>
                <div class="quiz-body">
                    @foreach (var option2 in QuestionsGolf[questionIndex5].Options)
                    {
                        <OptionCard Option="@option2" OnOptionSelected="OptionSelectedSolo"></OptionCard>   
                    }
                </div>
        }

questionIndex5 is just declared as 0 and it ++'s when selecting an option in OnOptionSelected.

Anyone got any tips for me how too proceed? :)

carlsby
  • 47
  • 6
  • 1
    You can use `.Where` with condition `Category == "something"`. For example `Questions.Where(question => question.Category == "Tennis")` returns an array with all `Question` objects matching the condition – AoooR Jan 20 '23 at 14:23
  • I tried this in my app-title div. @Questions.Where(question => question.Category == "Golf") But I'm getting this message in my category title: System.Linq.Enumerable+WhereListIterator`1[GusQuiz.Models.Question] What am I doing wrong? :( – carlsby Jan 20 '23 at 14:28
  • 1
    yes, because `.Where` return an array, and the `ToString` method of an array returns the message you get. You have to convert it to a string, see https://stackoverflow.com/questions/13426463/convert-an-array-to-string – AoooR Jan 20 '23 at 14:32
  • _"I tried this in my app-title div"_ why are you trying it there?? What are you trying to do there? It's a filter for the enumerator. So you should use it in a foreach: `@foreach (var question in Questions.Where(question => question.Category == "Golf"))` – JHBonarius Jan 20 '23 at 14:33
  • @AoooR no, it will not return an array. Linq `Where` returns an `IEnumerable`. It's not enumerated yet (and often doesn't explicitly have to be). – JHBonarius Jan 20 '23 at 14:35
  • @JHBonarius oh yes my bad ! thank you ! If you want to use all the IEnumarable use directly `FindAll` method of `List`, it is more efficient than `Where` and returns a List – AoooR Jan 20 '23 at 14:38
  • I should add that I'm a beginner in C# and I feel like there's alot of options to go on right now. Thanks for your help, how do you guys feel is the best way to proceed? – carlsby Jan 20 '23 at 14:38
  • I'm sorry for being stupid, but I tried to do this: string.Questions.AddRange(new List { q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21, q22, q23, q24, q25, q26, q27, q28, q29, q30, q31, q32 }); But it says "string does not contain a definition for Question" – carlsby Jan 20 '23 at 14:45
  • Why did you put `string.` in front of it? What does it have to do with a string? What are you trying to do? – JHBonarius Jan 20 '23 at 14:57
  • I'm trying to get the title "GOLF" from categories, or name of question into my quiz-header. But I only get these messages: System.Linq.Enumerable+WhereListIterator`1[GusQuiz.Models.Question] – carlsby Jan 20 '23 at 14:58
  • It's a bit of a messy design. The variable is called `QuestionsGolf`, so it should always be "Golf", or you did something wrong. You're showing part of your code, so we have to make a lot of assumptions. Where is the filtering (the "Where" clause) done? If you want to determine the category dynamically, it becomes more complex. And actually deserves it's own, new question on stackoverflow. – JHBonarius Jan 20 '23 at 15:05
  • btw, hard-labeling so many questions is probably not your best bet. You have enough questions that it's time to learn how to work with files or better yet a DB. – Bennyboy1973 Jan 20 '23 at 23:32

4 Answers4

1

The other answers already tell you how to filter by category:

IEnumerable<Question> golfQuestions = Questions
    .Where(question => question.Category.Equals("Golf"));

// or
List<Question> golfQuestionList = Questions
    .Where(question => question.Category.Equals("Golf"))
    .ToList();

You seem to be confused how to display this. Often, when working with Lists / IEnumerables we want to display all of them. This could look something like this:

@foreach (Question question in golfQuestions)
{
    <div class="app-title">
        @question.Category
    </div>
    <div class="quiz-header">
        @question.NameOfQuestion
    </div>
    <div class="quiz-body">
        @foreach (var option2 in question.Options)
        {
            <OptionCard Option="@option2" OnOptionSelected="OptionSelectedSolo">
            </OptionCard>   
        }
    </div>
}

If you only want to display a single question, converting to an IEnumerable makes little sense. I would suggest adding .ToArray(), but .ToList() works as well. Here is an example of displaying the third golf question:

Question[] golfQuestions = Questions
    .Where(question => question.Category.Equals("Golf"))
    .ToArray();

Question myQuestion = gofQuestions[2];


<div class="app-title">
    @myQuestion.Category
</div>
...
Jeanot Zubler
  • 979
  • 2
  • 18
0

You can create a method using the LINQ method Where to achieve this:

private IEnumerable<Question> GetQuestionsForCategory(string category)
{
    return Questions.Where(x => x.Category == category)
}
YungDeiza
  • 3,128
  • 1
  • 7
  • 32
0

You can use where Questions.Where(x => x.Category == "Golf") Or if you need to group questions by category then - Questions.GroupBy(x => x.Category) -- with this solution you will get all questions grouped into lists by their category

Gor Grigoryan
  • 297
  • 1
  • 7
  • Using this code I get this: System.Linq.Enumerable+WhereListIterator`1[GusQuiz.Models.Question] I'm not sure how to make it a string, I tried reading the link that @AoooR posted but I'm not really sure how to implement it. – carlsby Jan 20 '23 at 14:54
  • I'm guessing I should do something like this: @Questions.Where(x => x.Category == "Golf").Category But I get error message: IEnumerable' does not contain a definition for 'NameOfQuestion' and no accessible extension method 'NameOfQuestion' accepting a first argument of type 'IEnumerable' could be found (are you missing a using directive or an assembly reference?) – carlsby Jan 20 '23 at 14:57
  • what "string" you are trying to get? – Gor Grigoryan Jan 20 '23 at 14:58
  • This for example: Category = "Golf" – carlsby Jan 20 '23 at 14:59
  • Where statement returns all questions that has Golf category, if you need a specific field of question you can use Select -- Questions.Where(x => x.Category == "Golf").Select(x => x.NameOfQuestion) this will return list of "NameOfQuestion"s – Gor Grigoryan Jan 20 '23 at 15:02
  • Still getting this message: System.Linq.Enumerable+WhereSelectListIterator`2[GusQuiz.Models.Question,System.String] – carlsby Jan 20 '23 at 15:05
0

Anyone got any tips for me how too proceed? :)

Here's a slightly different implementation of your code that demonstrates some of the principles and patterns you can apply to help structure what your trying to do.

First a service for your data. You need to separate out the actual data pipeline from you UI. I use records to make the data in the data pipeline immutable (Read Only).

Your data object:

public record Question
{
    public string NameOfQuestion { get; init; } = string.Empty;
    public IEnumerable<string> Options { get; init; } = Enumerable.Empty<string>();
    public string Answer { get; init; } = string.Empty;
    public string Category { get; init; } = string.Empty;
}

Here's a demo QuestionProvider. Normally this will interface with a database or API so I've made it async.

public class QuestionProvider
{
    private List<Question> _questions = new();

    public Task Loading = Task.CompletedTask;

    public QuestionProvider()
        => this.Loading = this.LoadQuestions();

    public async ValueTask<IEnumerable<Question>> GetQuestions(QuestionQueryRequest request)
    {
        // Pretend I'm an async database or an API call
        await Task.Delay(100);
        var query = _questions.AsEnumerable();
        if (request.Category is not null)
            query = query.Where(item => item.Category.Equals(request.Category, StringComparison.CurrentCultureIgnoreCase));
        
        return query;
    }

    public async ValueTask<IEnumerable<string>> GetCategories()
    {
        await Task.Delay(100);
        return _questions.DistinctBy(item => item.Category).Select(item => item.Category);
    }
    private async Task LoadQuestions()
    {
        Question q1 = new Question
        {
            NameOfQuestion = "Vem är världens bästa golfspelare?",
            Options = new List<string>() { "Tiger Woods", "Matt Kuchar", "S.H. Kim", "Adam Scott" },
            Answer = "Tiger Woods",
            Category = "Golf"
        };
        // your existing code

        // pretend I'm a async task
        await Task.Delay(100);
    }
}

And then the View to manage the data for the UI page/component:

public class QuestionPresenter
{
    private readonly QuestionProvider _questionProvider;
    private bool _hasLoaded;
    public IEnumerable<string> Categories = Enumerable.Empty<string>();

    public string? Category { get; set; }

    public IEnumerable<Question> Questions { get; private set; } = Enumerable.Empty<Question>();

    public QuestionPresenter(QuestionProvider questionProvider)
        => _questionProvider = questionProvider;

    public async ValueTask GetQuestions()
    {
        // ensure the provider has loaded completely
        if (!_hasLoaded)
            await _questionProvider.Loading;

        this.Questions = await _questionProvider.GetQuestions(new(this.Category));
    }

    public async ValueTask Load()
    {
        // ensure the provider has loaded completely
        await _questionProvider.Loading;
        _hasLoaded= true;
        this.Categories = await _questionProvider.GetCategories();
    }
}

Service registration:

builder.Services.AddScoped<QuestionProvider>();
builder.Services.AddTransient<QuestionPresenter>();

And finally a page to get and display the data:

@page "/"
@inject QuestionPresenter Presenter
<PageTitle>Index</PageTitle>

<select class="form-select" value="@this.Presenter.Category" @onchange=SetCategory>
    @if (this.Presenter.Category is null)
    {
        <option selected disabled value="">-- Select a Category --</option>
    }
    @foreach (var category in Presenter.Categories)
    {
        <option value="@category">@category</option>
    }

</select>

@foreach (var question in this.Presenter.Questions)
{
    <div class="bg-light p-2 m-2">
        <div>
            Question: @question.NameOfQuestion
        </div>
        <div>
            Options: @OptionsList(question.Options)
        </div>
        <div>
            Answer: @question.Answer
        </div>
    </div>

}

@code {
    protected async override Task OnInitializedAsync()
        => await this.Presenter.Load();

    private async Task SetCategory(ChangeEventArgs e)
    {
        this.Presenter.Category = e.Value?.ToString() ?? null;
        if (this.Presenter.Category is not null)
            await Presenter.GetQuestions();
    }

    private RenderFragment<IEnumerable<string>> OptionsList => list => __builder =>
    {
        foreach(var item in list)
        {
            <span>&nbsp; @item;</span>
        }
    };
}

enter image description here

MrC aka Shaun Curtis
  • 19,075
  • 3
  • 13
  • 31