Win a copy of Machine Learning Systems: Designs that scale this week in the Scala forum
or Xamarin in Action: Creating native cross-platform mobile apps in the Android forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Filtering data, based on job test (with a few changes)  RSS feed

 
Saloon Keeper
Posts: 1604
56
Android Chrome IntelliJ IDE Java MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Recently this was what I had to complete this before my job application was even accepted. I thought that this may be a nice little programming challenge/diversion.
Requirements:
1. Provide a way to get a product’s total number of customer reviews whose ratings are within a given range (inclusive).
2. Add the following additional checks before creating a customer review:
    a. Your service should read a list of curse words. This list should not be defined in Java class.
    b. Check if Customer’s comment contains any of these curse words. If it does, throw an exception with a message.
    c. Check if the rating is not < 0.  If it is < 0, throw an exception with a message.

There was more to this challenge, which required using the Spring framework and a number of other source files.

My solution is listed below:

ListLoader.java

ProductModel.java

ProductReviews.java

WordFilter.java

Main.java

badwords.txt

This all works, but it is not the best solution and I'm pretty sure that others could create a better solution in any JVM language including Java, Kotlin, Scala, etc.
One issue is in WordFilter.java where I only split the review on a space, and there are many other characters what should be included.
There was no requirement for creating product reviews, but I created that so that I could test out the logic.
 
Marshal
Posts: 59108
180
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I can't see what is wrong with filtering whole words. Not like the time I went to a well‑known university for some special training and sent an email home about some beer. The beer was so strong I had to wash it down with some lighter beer. The automated filter found the end of wash and the word before down, decided it was something naughty, and changed it to XXXX.

Why are you using a List<String> for the naughty words? I didn't think your list of words was actually too bad
 
Pete Letkeman
Saloon Keeper
Posts: 1604
56
Android Chrome IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here the a solution done in Kotlin.
ListLoader.kt

ProductModel.kt


ProductReviews.kt

WordFilter.kt

Main.kt
 
Pete Letkeman
Saloon Keeper
Posts: 1604
56
Android Chrome IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:I can't see what is wrong with filtering whole words.


While it works, I do suspect that it can be done more efficiently.

Campbell Ritchie wrote:Why are you using a List<String> for the naughty words?


What do you think would be a better solution to this?  I have found it easy to use the List<String>, but that does not mean it's correct/proper.
 
Campbell Ritchie
Marshal
Posts: 59108
180
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What is wrong with a Set<String>?
 
Pete Letkeman
Saloon Keeper
Posts: 1604
56
Android Chrome IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:What is wrong with a Set<String>?


I'm not too sure, probably nothing in this case. Due to my lack of knowledge/experience I had not even thought of using Set<String>.
I need to get more familiar with all of the collection objects and properties.
Would you say that Set<String> is a better collection object then List<String> for this instance?
 
Campbell Ritchie
Marshal
Posts: 59108
180
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A List is an interface.
Because searching for elements can be done in linear time in an unsorted List, but in constant time in some Set implementations. If you have a Stream, you can do the testing in constant time.Yes, I know, peek is pretty awful. Another way you can do it is to add all the words in your input to another Set and look to see whether their intersection is empty.
 
Pete Letkeman
Saloon Keeper
Posts: 1604
56
Android Chrome IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Some really good points that I'll have to keep in mind as I move forward, continue to learn and program.

Thanks.
 
Campbell Ritchie
Marshal
Posts: 59108
180
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Pete Letkeman wrote:. . . Thanks.

That's a pleasure   It goes to show you, there are almost always different ways to implement something, and you will learn new things on this website.
 
Campbell Ritchie
Marshal
Posts: 59108
180
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The following took ages to write. Well over ten minutes:-KeyboardInput.getWholeLine() and KeyboardInput.getNextInt are similar to Scanner methods with similar names, but getWholeLine never returns an empty String. The naughtyWords file is a plain simple text file in UTF-8. I have tweked the code slightly since I first ran that app. I have also corrected the spellling mistake in cooks.

java NaughtyWordFinder
Enter message:
What a lovely restaurant. The food was good, the waiters polite, and they only charged £24.00 a head
Enter score as int: 8
All words OK.
[xxxx]$ java NaughtyWordFinder
Enter message:
The place was bl***y awful. Somebody tell the b****rd who cooks here to f**k off.                                                   
Enter score as int: 2
Exception in thread "main" java.lang.RuntimeException: Naughty words used: [b****rd, f**k, bl***y]
at NaughtyWordFinder.seekInput(NaughtyWordFinder.java:51)
at NaughtyWordFinder.main(NaughtyWordFinder.java:18)
[xxxx] java NaughtyWordFinder
Enter message:
What a lovely restaurant. The food was good, the waiters polite, and they only charged £24.00 a head
Enter score as int: -1
All words OK.
Exception in thread "main" java.lang.IllegalArgumentException: Negative score: -1
at NaughtyWordFinder.seekInput(NaughtyWordFinder.java:56)
at NaughtyWordFinder.main(NaughtyWordFinder.java:18)

If you print out the class for that Set
System.out.println(naughtyWordsSet.getClass().getName());
you get java.util.HashSet, which is a class I am familiar with. The rethrowing of Exceptions in line 32 is because I declared the Set as final.

[edit]Censor the naughty words with *****.
 
Campbell Ritchie
Marshal
Posts: 59108
180
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Pete Letkeman wrote:. . . . . .

!= ???
I may be mistaken about the next bit, but why are you not coming out of the loop as soon as found becomes true?
 
Pete Letkeman
Saloon Keeper
Posts: 1604
56
Android Chrome IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:!= ???
I may be mistaken about the next bit, but why are you not coming out of the loop as soon as found becomes true?


Where exactly is the loop in the above code?
I'm using findFirst() so that if a bad word is found then stop processing the stream.
If no bad word is found then I still want a value to test against so I'm using orElse("")
My code simply checks to see if any bad word is found. It does not provide any scoring.

Campbell Ritchie wrote:It goes to show you, there are almost always different ways to implement something, and you will learn new things on this website.


Yes, I am one those who is trying to constantly learn/improve.
 
Campbell Ritchie
Marshal
Posts: 59108
180
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Pete Letkeman wrote:. . . .Where exactly is the loop in the above code?  . . . .

D*mn! 💀☞🔪†🝏☠✊ There I  was reading the end of the code and thought it was the end of a loop.

Sorry

But do you really think you should use != on reference types as in the line 19 I quoted earlier? There is a String method which will do that sort of thing for you.
 
Pete Letkeman
Saloon Keeper
Posts: 1604
56
Android Chrome IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:There I  was reading the end of the code and thought it was the end of a loop.


No problem, we all make mistakes. I know that I have made plenty of mistakes and I will most likely continue to make mistakes.

Campbell Ritchie wrote:But do you really think you should use != on reference types as in the line 19 I quoted earlier? There is a String method which will do that sort of thing for you.


You are correct I should have used the equals() method so it would then become

Instead of what I previously wrote. Sometimes I get my programming languages mixed up. There is no need to use equals() in Kotlin.
 
Campbell Ritchie
Marshal
Posts: 59108
180
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Pete Letkeman wrote:, , , I should have used the equals() method . . .

Not with ""; there is another method for that.

Sometimes I get my programming languages mixed up. There is no need to use equals() in Kotlin.

Nor would there be in C#, where == is overloaded. It shows how careful one has to be when changing languages.
 
Pete Letkeman
Saloon Keeper
Posts: 1604
56
Android Chrome IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Do you mean isEmpty​()

API Docs wrote:public boolean isEmpty​()
Returns true if, and only if, length() is 0.
Returns:
true if length() is 0, otherwise false


https://docs.oracle.com/javase/9/docs/api/java/lang/String.html#isEmpty--

So I could have used

I wonder which method is more efficient equals() or isEmpty​()?
 
Campbell Ritchie
Marshal
Posts: 59108
180
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
isEmpty() will give you slightly faster execution. You probably won't notice the speed difference. All it does is something like this. Field access, field access, and equality to 0. Only three actions. No need for things like instanceof, casts, and comparisons of the fields of the other object.
Using isEmpty() will also alert whoever is reading the code to the fact that you know some of the more recent methods of String. You probably will notice that difference
 
Do you want ants? Because that's how you get ants. And a tiny ads:
Rocket Oven Kickstarter - from the trailboss
https://coderanch.com/t/695773/Rocket-Oven-Kickstarter-trailboss
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!