I've already worked out this solution for myself with PHP, but I'm curious how it could be done differently - better even. The two languages I'm primarily interested in are PHP and Javascript, but I'd be interested in seeing how quickly this could be done in any other major language today as well (mostly C#, Java, etc).
- Return only words with an occurrence greater than X
- Return only words with a length greater than Y
- Ignore common terms like "and, is, the, etc"
- Feel free to strip punctuation prior to processing (ie. "John's" becomes "John")
- Return results in a collection/array
Extra Credit
- Keep Quoted Statements together, (ie. "They were 'too good to be true' apparently")
Where 'too good to be true' would be the actual statement
Extra-Extra Credit
- Can your script determine words that should be kept together based upon their frequency of being found together? This being done without knowing the words beforehand. Example:
*"The fruit fly is a great thing when it comes to medical research. Much study has been done on the fruit fly in the past, and has lead to many breakthroughs. In the future, the fruit fly will continue to be studied, but our methods may change."*
Clearly the word here is "fruit fly," which is easy for us to find. Can your search'n'scrape script determine this too?
Source text: http://sampsonresume.com/labs/c.txt
Answer Format
- It would be great to see the results of your code, output, in addition to how long the operation lasted.
Perl in only 43 characters.
Here is an example of it's use:
If you need to list only the lowercase versions, it requires two more characters.
For it to work on the specified text requires 58 characters.
Here is the last example expanded a bit.
C# 3.0 (with LINQ)
Here's my solution. It makes use of some pretty nice features of LINQ/extension methods to keep the code short.
This is however far from the most efficient method, being
O(n^2)
with the number of words, rather thanO(n)
, which is optimal in this case I believe. I'll see if I can creater a slightly longer method that is more efficient.Here are the results of the function run on the sample text (min occurences: 3, min length: 2).
And my test program:
In C#:
Use LINQ, specifically groupby, then filter by group count, and return a flattened (selectmany) list.
Use LINQ, filter by length.
Use LINQ, filter with 'badwords'.Contains.
GNU scripting
Results:
With occurence greater than X:
Return only words with a length greater than Y (put Y+1 dots in second grep):
Ignore common terms like "and, is, the, etc" (assuming that the common terms are in file 'ignored')
Feel free to strip punctuation prior to processing (ie. "John's" becomes "John"):
Return results in a collection/array: it is already like an array for shell: first column is count, second is word.
F#: 304 chars
Another Python solution, at 247 chars. The actual code is a single line of highly dense Python line of 134 chars that computes the whole thing in a single expression.
A much longer version with plenty of comments for you reading pleasure:
The main trick here is using the itertools.groupby function to count the occurrences on a sorted list. Don't know if it really saves characters, but it does allow all the processing to happen in a single expression.
Results: