Anyway to make this more concise?

Here is my code:
data = readtable('alltimeteams.xlsx');
choice = listdlg('SelectionMode','Single', ...
'ListString', {'Atlanta Hawks', 'Boston Celtics'});
switch choice
case 1 % each statistic for the Hawks and their output
chosenstat = input("What statistic would you like to view? Please choose from Founding year, Age, Wins, Losses, Win-loss ratio, Championships, Abbreviation, Previous names. (CASE SENSITIVE)", 's');
if chosenstat == "Founding year"
fprintf("The founding year of the Atlanta Hawks is %s\n", data.From{1})
elseif chosenstat == "Age"
fprintf("The number of years the Atlanta Hawks have been established is %d\n", data.Yrs(1,1))
elseif chosenstat == "Wins"
fprintf("The number of wins for the Atlanta Hawks is %d\n", data.W(1,1));
elseif chosenstat == "Losses"
fprintf("The number of losses for the Atlanta Hawks is %d\n", data.L(1,1));
elseif chosenstat == "Win-loss ratio"
fprintf("The win-loss ratio for the Atlanta Hawks is %.3f\n", data.W_L_(1,1));
elseif chosenstat == "Championships"
fprintf("The number of championships won by the Atlanta Hawks is %d\n", data.Champ(1,1));
elseif chosenstat == "Abbreviation"
fprintf("The abbreviation for the Atlanta Hawks is %s\n", data.TeamAbbr{1});
elseif chosenstat == "Previous names"
fprintf("The number of previous names for the Atlanta Hawks is %d\n", data.Prev_Names_excl_Current_(1,1));
else
fprintf("That is not a valid statistic (it is case sensitive)")
end
end
Here is the data:
This code works, however im going to have 30 different cases, and this is a very "clunky" way to do this.
I was thinking to make a function for this, but how would I extract team specific data from the table in the function?
Please let me know of any ideas.
P.S The code for the Celtics is the same but obviously the statistics and outputs are specific to them

2 Comments

"but how would I extract team specific data from the table in the function?"
(edited to attach file)

Sign in to comment.

 Accepted Answer

dpb
dpb on 18 Nov 2025
Edited: dpb on 18 Nov 2025
You forgot to attach the input file, there's nothing to be done with just an image.
The way to make it more concise is to have the user specify the franchise and statistic(s) desired and then return those by matching the franchise and desired columns and return the data for those.
% caution air code...
data = readtable('alltimeteams.xlsx');
franchise=listdlg('SelectionMode','Single', 'ListString', data.Franchise); % all possible franchises
STATS=["Founding year","Age","Wins","Losses","Win-loss ratio","Championships","Abbreviation","Previous names"];
statistic=listdlg('SelectionMode','Single', 'ListString', STATS); % ditto statistics
teamData=data(franchise,:); % all franchise data
switch statistic
case 1
fprintf("The founding year of the %s is %d\n", teamData.Franchise,teamData.(statistic))
case 2
fprintf("The number of years the %s have been established is %d\n",teamData.Franchise,teamData.(statistic))
case 3
fprintf("The number of wins for the %s is %d\n",teamData.Franchise,teamData.(statistic))
etc, etc., ...
end
Generalize the statements to use the franchise name as data instead of each alone.
You could also make it somewhat more general by saving the format statements as an array of strings and then using a lookup indexs for the specific one by the index into the choice of statistic.
The general principle is to remove data from code entirely.

8 Comments

Ayaan
Ayaan on 18 Nov 2025
Edited: Ayaan on 18 Nov 2025
Only thing is that it comes up with this error:
"Error using matches
Not enough input arguments."
dpb
dpb on 18 Nov 2025
Edited: dpb on 18 Nov 2025
I said it was air code... <vbg>
teamData=data(Franchise,:);
I started thinking the returned was the value not the index -- you don't need a match at all, just the index to the row.
And, one could do all the indexing directly into the table as
data{franchase,statistic}
or
data.Francise(franchise)
As @Stephen23 suggests, explore the myriad of ways to dereference a table...
BTW, one could deal with multiple statistics relatively simply by allowing multi-select and then adding a loop around the case statement for the number of data items selected. If were to do that, it would probably be agoodthing™ to rewrite the output to put only the franchase first and then the list of statistics following.
Or, more in line of @Steven Lord's idea, if you were to use a uitable for display and name the fields as wanted, then you could just output the selected data as a table containing just the selected data without all the hassle of writing out long-winded sentences. And, that construct would do away with needing any looping to handle more than one of either variable.
Ayaan
Ayaan on 18 Nov 2025
Edited: Ayaan on 18 Nov 2025
Ive been messing with it and have actually gotten really close but the new problem is that the options for the statistic listdlg dont actually line up with the data, e.g. pressinng Founding year ends up showing the franchise name. It also only seems to work with the Hawks. Here is my new code. (Also I am a He but thanks for putting a question mark) (Also please lmk if this warrants a new post)
data = readtable('alltimeteams.xlsx');
franchise=listdlg('SelectionMode','single', 'ListString',data.Franchise); % all possible franchises
STATS = data.Properties.VariableNames(2:8);
statistic=listdlg('SelectionMode','Single', 'ListString', STATS);
teamData=data(franchise,:); % all franchise data
teamname = teamData(:,1); % extracts the name of the franchise
teamnamearray = table2array(teamname); % converts teamname into an array
name = string(teamnamearray); % converts teamnamearray into a string
teamstat = teamData(franchise, statistic) % retrieves the statistic based on the chosen statistic
teamstatarray= table2array(teamstat)
stat = string(teamstatarray)
switch statistic
case 1
fprintf("The founding year of the %s is %s\n ", name, stat)
end
this is what appears when choosing a team which isnt ATL
Error using () (line 133)
Row index exceeds table dimensions.
Error in PROJECT (line 10)
teamstat = teamData(franchise, statistic)
This is what appears when choosing "founded" statistic for ATL
The founding year of the Atlanta Hawks is Atlanta Hawks
dpb
dpb on 18 Nov 2025
Edited: dpb on 18 Nov 2025
Really need a dataset to work with to do actual final debugging...one can write air code that has the basic ideas, but without the real data set, one always ends up overlooking something unless it's a totally trivial exercise....and it's more effort to go to try to create your data structure to be sure it matches than most folks here (including me) are going to put into it, leaving those details to the poster. So, attach the Excel file and your latest code in one place.
I would not create another Q?, no...
ADDENDUM
Oh! It just dawned on me -- at least one oversight is that the list of statistics begins in the second column, not the first because the Franchise isn't one of them -- so the statistic index into the table needs to be the selection from the dialog plus 1. That's at least one issue...
If there are still issues beyond that one, set a breakpoint in the debugger and work through where the logic has an issue.
ADDENDUM SECOND:
teamstat = teamData(franchise, statistic)
teamData is a one row-high table already selected from the full data table so it would be
teamstat = teamData.(statistic+1)
You should be able to dispense with any table2array calls and use direct table addressing.
These are the little nits that one always overlooks when don't have the actual data at hand when trying to write interactive code...which is why to get good help, you need to provide enough information including data for folks to be able to do something with it.
Hers is the data sorry
It finally works, thanks so much for your help (and sorry that i didnt realise to attach the file earlier)
teamname = teamData(:,1); % extracts the name of the franchise
teamnamearray = table2array(teamname); % converts teamname into an array
name = string(teamnamearray); % converts teamnamearray into a string
The above would instead be
teamname=teamData.Franchise;
but instead of making local copies of the same data, just use the reference directly wherever you need it.
If you want a string, then make it one...
data=convertvars(data,'Franchise','string');
or, better yet, declare the desired string type when reading the input table to begin with.

Sign in to comment.

More Answers (1)

Rather than depending on users typing in the strings exactly as you're looking for them, if you know what variables will be in your table and know how you want to display the results, I would set the table's VariableNames property appropriately, use them in the display, and then use those variable names to index into the table. Let's take a sample table.
load patients
bloodPressure = table(LastName, Systolic, Diastolic);
head(bloodPressure)
LastName Systolic Diastolic ____________ ________ _________ {'Smith' } 124 93 {'Johnson' } 109 77 {'Williams'} 125 83 {'Jones' } 117 75 {'Brown' } 122 80 {'Davis' } 121 70 {'Miller' } 130 88 {'Wilson' } 115 82
Let's limit it to the first eight names/values, to avoid the double arrays I'll create later being too long.
bloodPressure = bloodPressure(1:8, :);
We can get the variable names.
varnames = bloodPressure.Properties.VariableNames
varnames = 1×3 cell array
{'LastName'} {'Systolic'} {'Diastolic'}
Now if I wanted to get all the Systolic values:
variableToRetrieve = varnames{2}
variableToRetrieve = 'Systolic'
allSystolicValues1 = bloodPressure.(variableToRetrieve) % double vector, or
allSystolicValues1 = 8×1
124 109 125 117 122 121 130 115
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
allSystolicValues2 = bloodPressure(:, variableToRetrieve) % 1 variable table, or
allSystolicValues2 = 8×1 table
Systolic ________ 124 109 125 117 122 121 130 115
allSystolicValues3 = bloodPressure{:, variableToRetrieve} % double vector
allSystolicValues3 = 8×1
124 109 125 117 122 121 130 115
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
If I wanted to have custom messages, I could put them in something like a dictionary or a struct array.
messages = struct('LastName', 'Patient''s last name', ...
'Systolic', 'Systolic blood pressure', ...
'Diastolic', 'Diastolic blood pressure');
firstPatient = bloodPressure(1, :);
for k = 1:length(varnames)
name = varnames{k};
fprintf("The variable %s of firstPatient is " + firstPatient{1, name} + ...
" and it represents %s.\n", name, messages.(name))
end
The variable LastName of firstPatient is Smith and it represents Patient's last name. The variable Systolic of firstPatient is 124 and it represents Systolic blood pressure. The variable Diastolic of firstPatient is 93 and it represents Diastolic blood pressure.
Note that the only places I hard-coded the names of the variables in the table were when I actually created it and when I created the struct array containing the messages. But you're already doing that in your if / elseif / else / end "switchyard".

1 Comment

"Rather than depending on users typing in the strings ..."
We fixed that some several questions ago, Steven; @Ayaan switched his(?) code from using input that did require typing in the strings to using a listdlg dropdown list from which to select the desired inputs. The code presented still has remnants of the original string matching in it including the admonition about case-sensitive and possibly unknown matches that are avoided this way.
It's probable there's still better choices, partciularly in that at present the user can get one and only one piece of data each time the code is run, but at least it does remove the direct typing.
I don't disagree that the table variable names could be renamed to match although with the list dialog return, one can simply use the list number instead so it doesn't matter too much although one could then also generalize the statistic in the display by using the VariableNames property, agreed.

Sign in to comment.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Products

Asked:

on 18 Nov 2025

Commented:

dpb
on 18 Nov 2025

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!