How to Properly Sort Flutter List with numbers and alphabet - list

I have a list in flutter which I want to sort like this
List<SearchUserResult> userSearchList = [
SearchUserResult(name: "Bright Isaac", age: 27, price: "10000"),
SearchUserResult(name: "Bright John", age: 7, price: "5000"),
SearchUserResult(name: "Phil Isaac", age: 20, price: "Negotiable"),
SearchUserResult(name: "Sunday", age: 16, price: "400")
];
What am trying to do is to get the highest price and the lowest price
userSearchList.sort((a, b) => a.price.compareTo(b.price)); //Get highest price
userSearchList.sort((b, a) => a.price.compareTo(b.price)); // Get lowest price
but I want that if am trying to get the lowest price it should be numbers like 10000 cause if you look at the list there is a Negotiable price and i don't want that to appear when sorting it only the numbers And also if you can help me i also want to be able sort it so that only the Negotiable without the numbers will show. Please how do i go about this.

Assuming you don't have the capability to do this on the server-side and just want to do this in client-side code, it shouldn't be too difficult.
If you really don't care about doing it in an optimal way, you could write something like this:
class PriceSearchUser {
num price;
SearchUserResult sur;
final PriceSearchUser(this.price, this.sur);
}
...
final priceSearchUsers = userSearchList
// create new list of price-UserSearchResult, with price in a sortable value (num)
.map((sur) => PriceSearchUser(num.tryParse(sur.price), sur))
// filter out any where the price wasn't able to be parsed into a number
.where((psu) => psu.price != null)
// make it in to a list so you can sort it
.toList();
final sortedSearchUserResults = priceSearchUsers
// sort that list! (note the double '.' - that makes it return
// the same object so that I can call the next function
..sort((a,b) => a.price.compareTo(b.price))
// get back to your original objects
.map((psu) => psu.sur)
// (optional) make it back into a list rather than an iterable
.toList();
If you're only doing this on a few users that should be adequate; if you're doing it on a whole bunch then you might want to think about optimizing or doing it in an isolate.
You can do something very similar with a "where" clause to get only the "Negotiable" prices.
However, as one of the comments mentioned, you should probably think about how exactly you do this. You say that you have a lot of code now but I guarantee you'll have more code later the next time this becomes a problem.
Also, this doesn't seem like a super-serious money app, but if it were you always need to be very careful about how you treat your monetary values. Doubles sometimes round to weird things! You could use something like this package.

Related

Dividing lists in Svelte

I had a recent urge to play with reading and formatting a GEDCOM (Genealogy) file and I'm using Svelte to accomplish this. But I'm stuck on a problem I'm not quite sure the best way to do it. Extracted from the GEDCOM file is a collection of names sorted by surnames. Let's say it's this:
Adams, John
Anderson, Neo
Cash, Johnny
Clapton, Eric
Cross, Christopher
Denver, John
The real list is quite a bit bigger and needs indicators for the letters of the alphabet. Essentially, I want to have the following as output:
Names starting with A:
Adams, John; Anderson, Neo;
Names starting with C:
Cash, Johnny; Clapton, Eric; Cross, Christopher;
Names starting with D:
Denver, John;
I have no problem spewing out the list. Svelte makes that easy enough. What I haven't figured out yet is how to interject the breaks. Each thing I've tried or thought about seems to be flawed. As far as I can tell, there's no good way to simply alter a variable as a loop progresses and there doesn't seem to be a way to get the previous item in the loop. Any suggestions for an approach?
I currently have this, but where to begin injecting the header?
{#each data.sort(compare) as n }
{#if n.ReverseName }
{n.ReverseName}
{/if}
{/each}
First of all, you want to ask yourself, "what is the format of the data output I want to obtain?". Considering your question and your objective to be able to loop through the output, you'd probably want the following structure:
output = [
[array of names starting with A, if any],
[array of names starting with B, if any],
etc.
]
I believe a relatively straightforward way to achieve this is with a reducer:
// start with sorting the input array so names are
// already properly sorted before being input to our reducer
const output = input.sort().reduce((acc, current) => {
// if the accumulator is an empty array,
// return the current value in a new sub array
// (the very first name pushed into the very first sub array)
if (acc.length === 0) {
return [ [ current ] ];
}
// otherwise, if the initial of the first name in
// the current (i.e. last created) sub array matches
// the initial of the current value, add that current
// value to the current sub array
const [ currentSub ] = acc.slice(-1);
if (currentSub[0].charAt(0) === current.charAt(0)) {
return [ ...acc.slice(0, -1), [ ...currentSub, current ] ];
}
// else add a new sub array and initialise it with the current value
return [ ...acc, [ current ] ];
}, []); // initialise with an empty array
The output array will have the desired shape [ [names starting with A, if any], [names starting with B, if any], ... ] and all that's left is for you to iterate through that output array:
{#each output as letterArray}
<p>Names starting with <strong>{letterArray[0].charAt(0)}</strong>:</p>
<p>{letterArray.join('; ')}</p>
{/each}
Or if you want to iterate over individual names, add an inner each block that iterates over letterArray. Many possibilities exist once your data is shaped the way you want it to be.
Demo REPL
Edit:
If input is dynamic (i.e. it is updated through the life of the component, either via a fetch or because it is received as a prop that might get updated), you can keep output automatically updated by turning its declaration into reactive code:
$: output = input.sort().reduce(...same code as above...)

Number of unique students that completed all 10 courses

I have a little formula problem that I would really appreciate some help with.
The list has columns with Student names that repeat, Course names that repeat, and course status that can be passed, not passed, or not started.
I would like to count the number of unique students that passed all 10 courses that are available.
I tried different variations of Calculate and COUNTROWS.
This is the formula I have at the moment that doesn't work
PassedAll =CALCULATE(DISTINCTCOUNT(Progress[Student]),Progress[Mark]="Passed",Progress[Course]="Course1"&&Progress[Course]="Course2")
I understand that && doesn't work in this scenario because in a single row it cannot be both courses. And I don't want to replace it with an OR, || operator because I want to count students that have Passed marks on each of these courses.
Can someone please recommend how to somehow replace the course section of the filter with something that will include all 10 courses?
If you want only number to show in "Card Visualization" then:
StudentPassed = countrows(filter(GENERATE(VALUES(Sheet1[Student]), ROW("CoursCompleted", CALCULATE( DISTINCTCOUNT(Sheet1[Course]), Sheet1[Mark] ="Passed"))), [CoursCompleted]= 10))
in my sample data 1 Student Passed all, 1 Student Passed 9courses, 1 Student Pass 8 (and no record for 2 of course).

Best way to compare phone numbers using Regex

I have two databases that store phone numbers. The first one stores them with a country code in the format 15555555555 (a US number), and the other can store them in many different formats (ex. (555) 555-5555, 5555555555, 555-555-5555, 555-5555, etc.). When a phone number unsubscribes in one database, I need to unsubscribe all references to it in the other database.
What is the best way to find all instances of phone numbers in the second database that match the number in the first database? I'm using the entity framework. My code right now looks like this:
using (FusionEntities db = new FusionEntities())
{
var communications = db.Communications.Where(x => x.ValueType == 105);
foreach (var com in communications)
{
string sRegexCompare = Regex.Replace(com.Value, "[^0-9]", "");
if (sMobileNumber.Contains(sRegexCompare) && sRegexCompare.Length > 6)
{
var contact = db.Contacts.Where(x => x.ContactID == com.ContactID).FirstOrDefault();
contact.SMSOptOutDate = DateTime.Now;
}
}
}
Right now, my comparison checks to see if the first database contains at least 7 digits from the second database after all non-numeric characters are removed.
Ideally, I want to be able to apply the regex formatting to the point in the code where I get the data from the database. Initially I tried this, but I can't use replace in a LINQ query:
var communications = db.Communications.Where(x => x.ValueType == 105 && sMobileNumber.Contains(Regex.Replace(x.Value, "[^0-9]", "")));
Comparing phone numbers is a bit beyond the capability of regex by design. As you've discovered there are many ways to represent a phone number with and without things like area codes and formatting. Regex is for pattern matching so as you've found using the regex to strip out all formatting and then comparing strings is doable but putting logic into regex which is not what it's for.
I would suggest the first and biggest thing to do is sort out the representation of phone numbers. Since you have database access you might want to look at creating a new field or table to represent a phone number object. Then put your comparison logic in the model.
Yes it's more work but it keeps the code more understandable going forward and helps cleanup crap data.

Python number averages using lists and keys

I'm working on a Python assignment and I'm totally stuck. Any assistance would be greatly appreciated. I know it's probably not as convoluted as it seems in my head... The details are below. Thanks very much.
Implement the following three functions (you should use an appropriate looping construct to compute the averages):
allNumAvg(numList) : takes a list of numbers and returns the average of all the numbers in the list.
posNumAvg(numList) : takes a list of numbers and returns the average of all the numbers in the list that are greater than zero.
nonPosAvg(numList) : takes a list of numbers and returns the average of all the numbers in the list that are less than or equal to zero.
Write a program that asks the user to enter some numbers (positives, negatives and zeros). Your program should NOT ask the user to enter a fixed number of numbers. Also it should NOT ask for the number of numbers the user wants to enter. But rather it should ask the user to enter a few numbers and end with -9999 (a sentinel value). The user can enter the numbers in any order. Your program should NOT ask the user to enter the positive and the negative numbers separately.
Your program then should create a list with the numbers entered (make sure NOT to include the sentinel value (-9999) in this list) and output the list and a dictionary with the following Key-Value pairs (using the input list and the above functions):
Key = 'AvgPositive' : Value = the average of all the positive numbers
Key = 'AvgNonPos' : Value = the average of all the non-positive numbers
Key = 'AvgAllNum' : Value = the average of all the numbers
Sample run:
Enter a number (-9999 to end): 4
Enter a number (-9999 to end): -3
Enter a number (-9999 to end): -15
Enter a number (-9999 to end): 0
Enter a number (-9999 to end): 10
Enter a number (-9999 to end): 22
Enter a number (-9999 to end): -9999
The list of all numbers entered is:
[4, -3, -15, 0, 10, 22]
The dictionary with averages is:
{'AvgPositive': 12.0, 'AvgNonPos': -6.0, 'AvgAllNum': 3.0}
EDIT: This is what I have so far, which I did pretty quick just to have a something to work with but I can't figure out how to implement the keys/dictionary like the assignment asks. Thanks again for any help.
print("This program takes user-given numbers and calculates the average")
counter = 0
sum_of_numbers = 0
first_question = int(input('Please enter a number. (Enter -9999 to end):'))
while first_question != -9999 :
ent_num = int(input('Please enter a number. (Enter -9999 to end):'))
sum_of_numbers = sum_of_numbers + ent_num
counter = counter + 1
first_question = int(input('Please enter a number (Enter -9999 to end):'))
print("Your average is " + str(sum_of_numbers/counter))
Welcome to Python programming, and programming in general!
From your code, I assume you are not entirely familiar with Python lists, dictionaries, and functions and how to use them. I'd suggest you look up tutorials for these; knowing how to use them will make your assignment much easier.
Here are some tutorials I found with some quick searches that might help:
Dictionary Tutorial,
List Tutorial,
Function Tutorial
When your assignment says to make three functions, you should probably make actual functions rather than trying to fit the functionality into your loop. For example, here is a simple function that takes in a number and adds 5 to it, then returns it:
def addFive(number):
return number + 5
To use it in your code, you would have something like this:
num = 6 # num is now 6
num = addFive(num) # num is now 11
So what you should do is create a list object containing all the numbers the user entered, and then pass that object into three separate functions - posNumAvg, nonPosAvg, allNumAvg.
Creating a dictionary of key-value pairs is pretty easy - first create the dictionary, then fill it with the appropriate values. For example, here is how I would create a dictionary like {'Hello': 'World'}
values = {}
values['Hello'] = 'World'
print(values) # Will print out {'Hello': 'World'}
So all you need to do is for each of the three values you need, assign the result of the function call to the appropriate key.
If this doesn't feel like quite enough for you to figure out this assignment, read the tutorials again and play with lists, dictionarys, and functions to try and get a feel for them. Good luck!
P.S. The append method of lists will be helpful to you. Try to figure out how to use it!

Python input, ifstatement, return

I have to create a function that takes an input, and returns a corresponding Grade.
So for example if the user inputs A+ output is 90%
or
if the input is A output is 80%
or
if the input is B output is 70%
I have some sort of Idea on how to do this... but I am having trouble on wrapping my head around on how I can return the statement??
def percent (percentage):
if ( percentage )== A+
return ("90%")
elif (percentage)== A
return ("80%")
Is this the correct way of going about it?
OK, so first, welcome to Python. Second, this is Pythonic way of doing this - define a dict:
grades = {'A+': "90%", 'A': "80%", ...}
then
return grades[precentage]
will do the job.
You need to protect against the case where the grade is not in the dict, for example, if the user entered some mistake, like G. There are a few ways to go about that:
A simple if:
if precentage in grades:
return grades[precentage]
else:
return "bad precentage"
After you get used to Python you will be more aesthetic about your code and will want to do better than state twice bote grades and precentage, so you can do simply:
return grades.get(precentage, "bad precentage")
Or using a special dict with default values:
import collections
grades = collections.defaultdict(lambda: "bad precentage", [("A+", "90%"), ("A", "80%")])
then
grades[precentage]
will automatically return "bad precentage" upon bad input.
#user2829744 You don't want to have to repeatedly call if statements based on what the percentage is, that would make the code unnecessarily long.
Instead, you want to have a list or tuple (a variable which stores multiple elements) that the program can compare the user's inputted value to, and then calculate the percentage mark.
Take this for example:
def percentage(per):
grades=["A+","A","B","C","D","E","F"]
percentage=("90%","80%","70%","60%","50%","40%","30%")
for i in range(7):
if per.upper()==grades[i]:
return percentage[i]
d="a"
print(percentage(d))
What happens is that i counts up to the number seven, and if the value of i in grades (let's say i is 5, then that would be grades[5] which would be an "E") then the function returns the value of i in the percentage tuple. In my case, the interpreter outputs 80%
Logically, your way of going about it (by actually dealing with every grade possible in separate if statements) would work too, however like I said your code would be longer and chances are you'd make a few typos along the way that you'd have to edit. Of course, my code has a few problems too, like what if the user enters a grade which I don't have in the tuple. This is easily fixable though as you would just need to tell the interpreter what to do if that happens.
A bit brief I know, but I hope this helps
You could do something like this
user_input = int(input("percentage: ")
if user_input < 0 and user_input > 10:
print('F")
And then you can just duplicate the code and change the numbers and the return grade
Hope it helps :)