I am having a large text file that will be use as an English dictionary database. (A real dictionary)
The user will type a word in a Search Bar and the app will return all the line of the text file that contains this word.
*-Each line explains the meaning of one word
-Some words are located on more than one line in my text file*
Here is my logic:
First I am looking for the word in self.entriesFromFile (which is one String of my Text File):
var range:NSRange? = self.entriesFromFile!.rangeOfString(searchText)
Then I find the Substring:
var substring:NSString = self.entriesFromFile!.substringToIndex(range!.location)
I split the Substring into lines
var substringArray:NSArray = substring.componentsSeparatedByString("\n")
Like this substringArray.count will return the current line where searchText has been found. I need the line number to identify the word in the dictionary for further functions.
I used this logic because I need it to be fast for the user, the text file contains more than 60,000 lines.
This works fine but it only return the first entry that have been found.
Could you help me find how to return all the lines number containing the searched word?
Thank you for your precious help
// I assume that searchText already has all file content
var lines = searchText.componentsSeparatedByString("\n")
var lineNumber = 0
for line in lines {
// It will fire 60.000 times
if string.rangeOfString("Some string you are searching for") != nil {
linesNumbers.append(lineNumber)
}
lineNumber++
}
Enumerate the lines and search each of them:
var lines: [String] = []
var lineNumber = 1; // or start with 0
self.entriesFromFile.enumerateLinesUsingBlock { line, stop in
if line.rangeOfString(searchedText) != nil {
lines.append(line) // or store the lineNumbers
}
lineNumber++
}
I wrote the code directly here, it may need changes to compile :P
Related
I have a String with different value every time:
String words = "My name is Rob Joe";
I want to get only last word
Joe
but every time I don't know how many words the string consists of
String words = "My name is Rob Joe";
var array = words.split(" "); // <-- [My, name, is, Rob, Joe]
print(array.last); // output 'Joe'
In Flutter(Dart), you can get the last word of a string by splitting the string into an array of substrings using the split method and then accessing the last element of the resulting array. Here's an example:
String words = "My name is Rob Joe";
List<String> wordsArray = myString.split(" ");
String lastWord = wordsArray[wordsArray.length - 1];
print(lastWord); // "Joe"
Instead of splitting, you can also use substring and lastIndexOf:
final words = "My name is Rob Joe";
final lastWord = words.substring(words.lastIndexOf(" ") + 1);
print(lastWord);
If you want to find the last word, you should first properly define what a "word" is.
It's clearly obvious here, which is why it's doubly important to write it down, because something else may be just as obvious to someone else.
(Read: Nothing is obvious. Document it all!)
But let's say that a word is a maximal contiguous sequence of ASCII letters.
Then that's what you should look for.
Splitting on space characters works for this string, but won't if you have punctuation, or trailing whitespace, or any number of other complications.
I'd probably use a RegExp:
// Matches a word. If used properly, only matches entire words.
var wordRE = RegExp(r"[a-zA-Z]+");
// Assume at least one word in `words`. Otherwise need more error handling.
var lastWord = wordRe.allMatches(words).last[0]!;
This can be a little inefficient, if the string is long.
Another approach that might be more efficient, depending on the RegExp implementation, is to search backwards:
/// Captures first sequence of [a-zA-Z]+ looking backwards from end.
var lastWordRE = RegExp(r"$(?<=([a-zA-Z]+)[^a-zA-Z]*)");
var lastWord = lastWordRE.firstMatch(words)?[1]!;
If you don't want to rely on RegExps (which are admittedly not that readable, and their performance is not always predictable), you can search for letters manually:
String? lastWord(String words) {
var cursor = words.length;
while (--cursor >= 0) {
if (_isLetter(words, cursor)) {
var start = 0;
var end = cursor + 1;
while (--cursor >= 0) {
if (!_isLetter(words, prev)) {
start = cursor + 1;
break;
}
}
return words.substring(start, end);
}
}
return null;
}
bool _isLetter(String string, int index) {
var char = string.codeUnitAt(index) | 0x20; // lower-case if letter.
return char >= 0x61 /*a*/ && char <= 0x7a /*z*/;
}
But first of all, decide what a word is.
Some very real words in common sentences might contain, e.g., ' or -, but whether they matter to you or not depends on your use-case.
More exotic cases may need you to decide whether"e.g." is one word or two? Is and/or? Is i18n?
Depends on what it'll be used for.
I'm a beginner in dart.
void main() {
var abf = '+37.4054-122.0999/';
var abf2;
abf2 = abf.replaceAll("+"," ");
var abf1 = abf2.split(RegExp('(?=[+-])'));
print (abf1[0]);
print (abf1[1]);
}
The above code splits abf into two values for me
I want to remove the ending '/'. I tried many split methods using other variables but it's not removing the '/' even though its removing the '+'.
It's not really clear what you're trying to do with the split.
But if you're looking the remove the / this should work:
String number = '+37.4054-122.0999/';
number = number.replaceAll("/"," ");
You can create substring from this while you like to remove last element.
String abf = '+37.4054-122.0999/';
final result = abf.substring(0, abf.length - 1);
print(result);
Dart's List class has a built-in removeLast method. Maybe you can try to split the string and then removing the last element:
String str = "str";
String newStr = str.split(''). removeLast().join('');
This is the first time I am trying to parse a CSV file; I have only worked with JSON files before. I understand that CSV is an abbreviation for comma separated values. I have a CSV file with a list of all rest stops on interstate highways across the United States; however, the values in this file are not separated by a comma. I was wondering if anyone could help me parse this file into object? My aim is to sort through this file and put each interstate belonging to a particular state in the corresponding object(state). For instance Interstate 5 (I-5) spans the entire western coast of the U.S. it starts from the Canadian border and goes through Washington, Oregon, and California all the way to the Mexican border. Consequently, I-5 should be in the "Washington", "Oregon", and "California" objects. The code below is my attempt to remove all punctuation and replace them with only a comma to get a regular CSV file. Sequentially, after I have created a regular CSV file I try to sort as explained above. This is my code:
var californiaInterstates: [InterstateAttributes] = []
func parseCSVFile(){
var fullString: String = ""
var restStops: [String] = []
guard let path = NSBundle.mainBundle().pathForResource("Rest_Areas", ofType: "csv") else{
print("There was an error parsing the data file!")
return
}
do{
fullString = try String(contentsOfFile: path)
}catch let error as NSError{
print(error.debugDescription)
}
restStops = fullString.componentsSeparatedByString("\r")
for (index, restStop) in restStops.enumerate() {
let element = restStop.componentsSeparatedByString("\"").joinWithSeparator("").componentsSeparatedByString("]").joinWithSeparator("").componentsSeparatedByString("[").joinWithSeparator("").componentsSeparatedByString("|").joinWithSeparator(",")
restStops[index] = element
}
for (index, restStop) in restStops.enumerate(){
//print(index)
let restStopArray = restStop.componentsSeparatedByString(",")
if restStopArray[2] == "CA" {
let interstateAttributes = InterstateAttributes()
interstateAttributes.latitude = Double(restStopArray[0])
interstateAttributes.longitude = Double(restStopArray[1])
interstateAttributes.state = restStopArray[2]
interstateAttributes.interstate = restStopArray[3]
interstateAttributes.bound = restStopArray[4]
interstateAttributes.description = restStopArray[5]
interstateAttributes.name = restStopArray[6]
interstateAttributes.RR = restStopArray[7]
interstateAttributes.PT = restStopArray[8]
interstateAttributes.VM = restStopArray[9]
interstateAttributes.pets = restStopArray[10]
interstateAttributes.HF = restStopArray[11]
interstateAttributes.RVDump = restStopArray[12]
californiaInterstates.append(interstateAttributes)
}
}
}
I have tried to sort the highways in California as an example. This code does not work and gives an error because some of the indexes are out of range when I try to access interstate attributes. Can you please help me parse and sort this CVS file?
Attached is the CSV file:
RestAreasCombined_USA.csv
If you have any trouble downloading the file please let me know.
Thank you in advance for taking the time to read my post!
The problem you have is that this is not completely a .csv file. The "Details" column, column 4, is just a string that (unfortunately for you) may contain commas itself.
What you need to do is expect the first 3 columns to be there and then do more parsing of the sub items.
For example, the interstate item is not a separate field; it's part of the type notes column, column 3 (and is not guaranteed to be an interstate; look at rows 14 and 22, for example, relating to US highways).
Also, why are you testing the third column for "CA"? None of the rows in the file you linked have that at all...
And then, when you get to string entries 4- length, you are going to have to just test them against "RR", "PT", "VM", "Pets", "HF", "Gas", Food", "RV Dump", etc. to set the appropriate boolean values for your exit.
I wrote the following function that reads through the list of media items in my iTunes directory and returns the music files. I need to return the "song titles" but when I run it the items returned are in an unknown format. I am pretty sure I need to run them through a property filter or use some conversion to get the actual names correctly. At the end I want to output the contents in an array of Strings. I only run the loop four times in the screen shot attached. Can anyone point me to a missing conversion? It looks like the output is in hex format but not clear on that.
class func readMusicFiles() -> NSMutableArray {
//var songDecoded:[NSMutableArray]
let result = NSMutableArray()
let allSongsQuery:MPMediaQuery = MPMediaQuery.songsQuery();
let tempArray:NSArray = allSongsQuery.items!;
for item:AnyObject in tempArray {
if (item is MPMediaItem) {
let temp = item as! MPMediaItem;
if (temp.mediaType != MPMediaType.Music) {
continue;
}
result.addObject(item);
}
}
print(result)
return result
}
}
The output looks like this
The "hex" is not a "format"; it's merely an indication of the memory address of the object. Ignore it.
You've got your media items (songs in this case). Now, instead of saying print(result), ask for their titles:
for song in result {
print(song.title)
}
Or, to make a new array:
let titles = result.map {$0.title}
(Also, do not declare your function to return an NSMutableArray. That's a Cocoa thing. Try to stick to Swift arrays. For example, if you are going to end up with an array of titles, those are strings, so return a [String].)
Is there a function to capitalize each word in a string or is this a manual process?
For e.g. "bob is tall"
And I would like "Bob Is Tall"
Surely there is something and none of the Swift IOS answers I have found seemed to cover this.
Are you looking for capitalizedString
Discussion
A string with the first character in each word changed to its corresponding uppercase value, and all remaining characters set to their corresponding lowercase values.
and/or capitalizedStringWithLocale(_:)
Returns a capitalized representation of the receiver using the specified locale.
For strings presented to users, pass the current locale ([NSLocale currentLocale]). To use the system locale, pass nil.
Swift 3:
var lowercased = "hello there"
var stringCapitalized = lowercased.capitalized
//prints: "Hello There"
Since iOS 9 a localised capitalization function is available as capitalised letters may differ in languages.
if #available(iOS 9.0, *) {
"istanbul".localizedCapitalizedString
// In Turkish: "İstanbul"
}
An example of the answer provided above.
var sentenceToCap = "this is a sentence."
println(sentenceToCap.capitalizedStringWithLocale(NSLocale.currentLocale()) )
End result is a string "This Is A Sentence"
For Swift 3 it has been changed to capitalized .
Discussion
This property performs the canonical (non-localized) mapping. It is suitable for programming operations that require stable results not depending on the current locale.
A capitalized string is a string with the first character in each word changed to its corresponding uppercase value, and all remaining characters set to their corresponding lowercase values. A “word” is any sequence of characters delimited by spaces, tabs, or line terminators (listed under getLineStart(_:end:contentsEnd:for:)). Some common word delimiting punctuation isn’t considered, so this property may not generally produce the desired results for multiword strings.
Case transformations aren’t guaranteed to be symmetrical or to produce strings of the same lengths as the originals. See lowercased for an example.
There is a built in function for that
nameOfString.capitalizedString
This will capitalize every word of string. To capitalize only the first letter you can use:
nameOfString.replaceRange(nameOfString.startIndex...nameOfString.startIndex, with: String(nameOfString[nameOfString.startIndex]).capitalizedString)
Older Thread
Here is what I came up with that seems to work but I am open to anything that is better.
func firstCharacterUpperCase(sentenceToCap:String) -> String {
//break it into an array by delimiting the sentence using a space
var breakupSentence = sentenceToCap.componentsSeparatedByString(" ")
var newSentence = ""
//Loop the array and concatinate the capitalized word into a variable.
for wordInSentence in breakupSentence {
newSentence = "\(newSentence) \(wordInSentence.capitalizedString)"
}
// send it back up.
return newSentence
}
or if I want to use this as an extension of the string class.
extension String {
var capitalizeEachWord:String {
//break it into an array by delimiting the sentence using a space
var breakupSentence = self.componentsSeparatedByString(" ")
var newSentence = ""
//Loop the array and concatinate the capitalized word into a variable.
for wordInSentence in breakupSentence {
newSentence = "\(newSentence) \(wordInSentence.capitalizedString)"
}
// send it back up.
return newSentence
}
}
Again, anything better is welcome.
Swift 5 version of Christopher Wade's answer
let str = "my string"
let result = str.capitalized(with: NSLocale.current)
print(result) // prints My String