I'm learning Swift and I'd just like to know the best way to go about reading in a text file, breaking it up into lines and then taking each word on each line and turn the words into strings that can be loaded into class initialisers.
For example, if I have this text file:
**This is just a random text file, and the text on this line
and this line is not needed**
birth year birth month birth day favourite colour
1990 11 12 red
1995 2 4 pink
1992 5 3 orange
1987 3 19 blue
I want to take the birth year, birth month, birth day and favourite colour from each line and then load it into a class like this:
Person(birthYear: 1990, birthMonth: 11, birthDay: 12, favouriteColour: red)
The text file that I want to read in might have an uneven amount of spaces so the output will look like this (for the given text file):
["**This", "is", "just", "a", "random", "text", "file,", "and", "the", "text", "on", "this", "line"]
["and", "this", "line", "is", "not", "needed**"]
["birth", "year", "", "", "", "birth", "month", "", "", "birth", "day", "", "", "", "", "favourite", "colour"]
["1990", "", "", "", "", "", "", "", "", "", "11", "", "", "", "", "", "", "", "", "", "", "", "12", "", "", "", "", "", "", "", "", "", "", "", "red"]
["1995", "", "", "", "", "", "", "", "", "", "", "2", "", "", "", "", "", "", "", "", "", "", "", "", "4", "", "", "", "", "", "", "", "", "", "", "", "pink", ""]
["1992", "", "", "", "", "", "", "", "", "", "", "5", "", "", "", "", "", "", "", "", "", "", "", "", "3", "", "", "", "", "", "", "", "", "", "", "", "orange"]
["1987", "", "", "", "", "", "", "", "", "", "", "3", "", "", "", "", "", "", "", "", "", "", "", "19", "", "", "", "", "", "", "", "", "", "", "", "blue"]
Here is my code so far:
let path = "path to my file"
if let contents = try? String(contentsOfFile: path) {
// breaking the text file up into lines
let lines = contents.components(separatedBy: "\n")
// breaking the lines up into wordsw
for line in lines {
let elements = line.components(separatedBy: " ")
print(elements)
}
}
I'm just wondering what the best way to deal with white space in these cases would be. Thank you in advance for your replies.
You can use a simple solution to clean all Tabs and Double spaces. Try use this piece of code.
func cleanTabsAndSpace(in text:String) -> String {
var newText = text
newText = newText.filter{ $0 != "\t" }.reduce(""){ str, char in
if let lastChar = str.last, lastChar == " " && lastChar == char {
return str
}
return str + String(char)
}
return newText.trimmingCharacters(in: .whitespacesAndNewlines)
}
After create this function you can call it inside your function
if let contents = try? String(contentsOfFile: path) {
// Clean undesired chars
let cleanContent = cleanTabsAndSpace(in: contents)
// breaking the text file up into lines
let lines = cleanContent.components(separatedBy: "\n")
// breaking the lines up into wordsw
for line in lines {
let elements = line.components(separatedBy: " ")
print(elements)
}
}
With this you will have all your content separated as you wish. Now you have just to follow as you want, parsing the content as you want and create your objects.
I'm just considering this structure you described in your question.
Good luck friend and Feel free to contact me if you need something more.
There is a split(separator:maxSplits:omittingEmptySubsequences:)
method which allows to split a String
into an array of SubStrings.
In contrast to components(separatedBy:) this method (by default)
omits empty substrings caused by consecutive separator characters.
Example:
let line = "1990 11 12 red"
let elements = line.split(separator: " ")
print(elements) // ["1990", "11", "12", "red"]
Here element has the type [SubString], i.e. the substrings reference
the original character storage in line, without duplicating it.
If you need "real" strings, then change it to
let elements = line.split(separator: " ").map(String.init)
Applied to your case:
if let contents = try? String(contentsOfFile: path) {
let lines = contents.components(separatedBy: "\n")
for line in lines {
let elements = line.split(separator: " ")
print(elements)
}
}
Related
I have a login component that after the user have login, I went ahead to get the data to my local storage and if the login is successeful, which means the data is true, I want to update my component by redirecting the user another components and update my component with the user information. Right now the login went successfully and data been passed to the local storage, but, I don't get redirected, because in the next componet, the update is not happening. and in my console logs waning error that said "Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function."
here is my login component
const user = JSON.parse(localStorage.getItem("user"));
const applicationForm = {
firstname: "",
lastname: "",
middlename: "",
gender: "",
dob: "",
phone: "",
email: "",
country: "",
crr_state: "",
institution: "",
fac_dept: "",
year_entry: "",
matric_number: "",
student_status: "",
edu_level: "",
applying_as: "",
team_members: "",
idea_grant: "",
category: "",
current_status: "",
area_of_interest: "",
formStatus: "Save and Continur later",
id: user ? user._id : "",
idea_summary: "",
video_url: "",
textChange: "Sumbit",
};
const NUICAppForm = () => {
const [formData, setFormData] = useState(applicationForm);
const [states, setStates] = useState(null);
const categoryList = [
"Renewable Energy Technologies",
"Satellite Communication Technologies",
"Drone Technologies",
"E-commerce Development",
"Smart AgricTech",
"Mobile Computing and 5G Networks",
];
const {
firstname,
lastname,
middlename,
gender,
dob,
phone,
email,
country,
crr_state,
institution,
fac_dept,
year_entry,
matric_number,
student_status,
edu_level,
current_status,
applying_as,
team_members: {
memberFullname1,
memberEmail1,
memberPhone1,
memberFullname2,
memberEmail2,
memberPhone2,
memberFullname3,
memberEmail3,
memberPhone3,
memberFullname4,
memberEmail4,
memberPhone4,
memberFullname5,
memberEmail5,
memberPhone5,
},
idea_grant,
category,
area_of_interest,
idea_summary,
video_url,
formStatus,
id,
textChange,
} = formData;
const clear = () => {
window.localStorage.clear();
};
const handleSubmit = (e) => {
e.preventDefault();
setFormData({ ...formData, textChange: "Submitting" });
axios
.post("https://i-next-backend.herokuapp.com/nuic/form/register", {
firstname,
lastname,
middlename,
gender,
dob,
phone,
email,
country,
crr_state,
institution,
fac_dept,
current_status,
year_entry,
matric_number,
student_status,
edu_level,
applying_as,
team_members: {
memberFullname1,
memberEmail1,
memberPhone1,
memberFullname2,
memberEmail2,
memberPhone2,
memberFullname3,
memberEmail3,
memberPhone3,
memberFullname4,
memberEmail4,
memberPhone4,
memberFullname5,
memberEmail5,
memberPhone5,
},
idea_grant,
category,
area_of_interest,
idea_summary,
formStatus,
video_url,
id: user._id,
})
.then((res) => {
setFormData({
...formData,
firstname: "",
lastname: "",
middlename: "",
gender: "",
dob: "",
phone: "",
email: "",
country: "",
crr_state: "",
current_status: "",
institution: "",
fac_dept: "",
year_entry: "",
matric_number: "",
student_status: "",
edu_level: "",
applying_as: "",
team_members: {
memberFullname1: "",
memberEmail1: "",
memberPhone1: "",
memberFullname2: "",
memberEmail2: "",
memberPhone2: "",
memberFullname3: "",
memberEmail3: "",
memberPhone3: "",
memberFullname4: "",
memberEmail4: "",
memberPhone4: "",
memberFullname5: "",
memberEmail5: "",
memberPhone5: "",
},
idea_grant: "",
category: "",
area_of_interest: "",
idea_summary: "",
video_url: "",
id,
textChange: "Application submitted for review ",
formStatus: "Pending application",
});
setFormData({
...formData,
textChange: "Application Submitted",
formStatus: "Application Pendig",
});
})
.catch((err) => {
setFormData({
...formData,
firstname: "",
lastname: "",
middlename: "",
gender: "",
dob: "",
phone: "",
email: "",
country: "",
crr_state: "",
current_status: "",
institution: "",
fac_dept: "",
year_entry: "",
matric_number: "",
student_status: "",
edu_level: "",
applyisng_as: "",
team_members: {
memberFullname1: "",
memberEmail1: "",
memberPhone1: "",
memberFullname2: "",
memberEmail2: "",
memberPhone2: "",
memberFullname3: "",
memberEmail3: "",
memberPhone3: "",
memberFullname4: "",
memberEmail4: "",
memberPhone4: "",
memberFullname5: "",
memberEmail5: "",
memberPhone5: "",
},
idea_grant: "",
category: "",
area_of_interest: "",
idea_summary: "",
video_url: "",
formStatus: "",
id,
});
setFormData({ ...formData, textChange: err.response.data.message });
});
};
useEffect(() => {
const fetchStates = async () => {
const result = await axios(
"https://nigerian-states-info.herokuapp.com/api/v1/states"
);
setStates(result.data.data);
};
fetchStates();
}, [user]);
As you can see above in the useEffect, first I defined a function that check if the user exist outside the ueEffect which the chechking is true but can update when a user login, the I thought of using useState to passed that value but still, it did not works. Please any suggestion on how to update my component when the signin went through ?
Please help.....
Your useEffect only runs once and that is right after the component has been loaded. Right now its not aware of any other changes since you have given empty dependency array to it.
To suggest a solution in your case, why don't you just call
history.push("/application")
after you set the data to localStoare? That is after the line
localStorage.setItem("user", JSON.stringify(res.data));
and remove the useEffect
You can have a Force Update by React hooks.
Declare const [render, setRerender] = useState(false);
then call the following when you want to update the UI, setRerender(!rerender);
I have created a fixed size array to collect user data from textfields. Each textfield is in a different cell. So I'm collecting all user answers in one fixed array
var userSelectionText = [String](repeating: "", count: 17)
What is really strange is that the array size gets enlarged with +1 every time I insert a string in a certain index in the array according to the row number of the cell.
self.userSelectionText.insert(diseaseSelectionArray[row], at: tappedTextFieldTag)
When I print out the array at first load of the view I have 17 items
["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]
After adding a string in a certain index of the fixed sized array I have 17 items + 1
["", "", "No", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]
Why? I need them fixed to reflect the exact number of rows in the tableview
You're inserting (adding) elements into the array, but what you want is to replace the existing elements:
var array = ["", "", ""]
print(array)
print(array.count)
array.replaceSubrange(Range(0 ... 0), with: ["1"])
print(array)
print(array.count)
This outputs:
["", "", ""]
3
["1", "", ""]
3
Or, even shorter (thanks #Joakim Danielson):
array[0] = "1"
In Logic Apps I have this function which replaces double double quotes with a zero for some strings.
How can I replicate this in Javascript?
```javascript
replace(replace(replace(replace
(replace(body('HTTP_2'),'"PR_RENT":""','"PR_RENT":0'),
'"PR_ID":""','"PR_ID":0'),'"PR_USUM":""','"PR_USUM":0'),'"PR_LEAS":""','"PR_LEAS":0'),
'"PR_USER8":""','"PR_USER8":0')
```
This question has been answered [here] (Nested replace of strings with double quotes in Javascript). The problem is that this solution required an Integration Account which costs quite a bit of money. Is there any way to do this without an Integration Account?
Besides the solution of javascript with integration account, we can also add azure function in logic app and write the js code in azure function to meet your requirements. Please refer to the steps below:
Create an azure function app in azure portal by referring this tutorial. But this tutorial is creating .net function, we need to create nodejs function, so you should select "Node.js" as "Runtime stack".
In "Hosting" tab, you can choose "Consumption" as "Plan type".
Consumption plan can help us save money, you can refer to this tutorial to know the cost of azure function.
After creating the azure function app, please go to your function app and create a function. Refer to the screenshot below and choose "HTTP trigger" in the next step.
Put the js code to HttpTrigger function.
Then we come back to logic app, create "Azure Functions" connector by referring this tutorial, choose the httptrigger function which you created just now.
Provide your json data as the request body to azure function action.(I have stored your json data as a variable named "data").
Run the logic app, get the result which we expect.
The whole output json data show as below:
{
"Payload": [
{
"RLS_GROUP": "",
"PR_SNAM": "700063",
"PR_OWN": "qqq",
"PR_REF": "",
"PR_NAME": "Bqqq12",
"PR_ADD1": "qqq",
"PR_ADD2": "INDUSTRIAL ESTATE",
"PR_ADD3": "23 INDUSTRIAL ESTATE",
"PR_ADD4": "yyy",
"PR_ADD5": "",
"PR_ADD6": "GB",
"PR_POST": "WQDQWD",
"PR_TEL": "23213",
"PR_TELX": "21312312",
"PR_FAX": "",
"PR_CONT": "",
"PR_NUNIT": "",
"PR_INT": "",
"PR_TENR": "LEASED",
"PR_QDAY": "",
"PR_CLSS": "",
"PR_DRCT": "Closing",
"PR_AGENT": "",
"PR_NOWN": "",
"PR_BOWN": "",
"PR_SOL": "",
"PR_HSTT": "",
"PR_HEND": "",
"PR_HAMT": "",
"PR_PFREQ": "",
"PR_NTENT": "",
"PR_NFLR": "",
"PR_GRA": "",
"PR_WATER": "",
"PR_RATVAL": "",
"PR_RTCT": "",
"PR_SCHG": "",
"PR_OCHG": "",
"PR_GFA": "",
"PR_ZONEA": "",
"PR_ZONEB": "",
"PR_ZONEC": "",
"PR_UPDATE": "",
"PR_UTIME": "",
"PR_UUSER": "",
"PR_HIST": "",
"PR_TAXYN": "",
"PR_TAX": "",
"PR_START": "",
"PR_END": "",
"PR_FREQ": "",
"PR_QTR": "",
"PR_NDUE": "",
"PR_TAXRUN": "",
"PR_OUTLET": "",
"PR_INLET": "",
"PR_VAL": "",
"PR_CST": "",
"PR_FRWA": "",
"PR_FRWB": "",
"PR_PRINT": "",
"PR_NL": "",
"PR_CURRS": "",
"PR_NEXTS": "",
"PR_VAT": "D",
"PR_USER": "",
"PR_VQDAY": "",
"PR_OBS1": "STANDARD NORTH",
"PR_TYPE": "Property",
"PR_VATDATE": "",
"PR_FUTHER": "",
"PR_RESTEN": "",
"PR_CAPGOODS": "",
"PR_INSEE": "",
"PR_CURR": "",
"PR_AQDATE": "20190917",
"PR_USER1": "Office",
"PR_USER2": "Yes",
"PR_USER3": "",
"PR_USER4": "",
"PR_USER5": "20190917",
"PR_USER6": "",
"PR_USER7": "",
"PR_USER8": 0,
"PR_USER9": "",
"PR_USER10": "",
"PR_OBS2": "",
"PR_OBS3": "",
"PR_OBS4": "",
"PR_OBS5": "",
"PR_OBS6": "",
"PR_OBS7": "UK",
"PR_OBS8": "",
"PR_OBS9": "",
"PR_SOLD": "0",
"PR_DATESOLD": "20200917",
"PR_LAND": "",
"PR_LANDUM": "",
"PR_FREE": "",
"PR_ID": 0,
"PR_BTYP": "F",
"PR_LEAS": 0,
"PR_RENT": 0,
"PR_USUM": 0,
"PR_FBUI": 0,
"PR_DREN": "",
"PR_USRC": "",
"PR_RSRC": "",
"PR_LSRC": "",
"PR_ELSR": "",
"PR_EGRS": "",
"PR_PROR": "",
"PR_BSTA": "",
"PR_LNAM": "123123213",
"PR_SITE": "",
"PR_REGION": "",
"PR_DESC": ""
}
]
}
The five fields have been replaced with 0.
The advantage of this solution is the consumption plan cost money only when your functions are running. I think it will be cheaper than integration account.
im trying to get the options selected but im getting only the last selected option from the select input..
state never gets updated to multiple options..just the last option ,ive tried many options but nothing is saving the multile options.
currentPage: 3,
custFirstname: "",
custLastName: "",
custPhoneNum: "",
custEmail: "",
vehicleNum: "",
vehicleMake: "",
vehicleModel: "",
defects_tank: "",
defects_tankLogo: "",
defects_lightglass: "",
defects_seatcover: "",
defects_crashgaurd: "",
defects_mirrors: "",
defects_indicators: "",
electricals_headlight: "y",
electricals_tailLight: "y",
electricals_console: "y",
electricals_indicatorF: "y",
electricals_indicatorR: "y",
electricals_horn: "y",
petrolLevel: "",
battery: "",
jobs: [],
job: {
description: "",
repObserv: "",
customerReq: "",
typeOfService: "",
charges: "",
services: []
}
};
im updating the state -> job -> services
handleJobsDropDown = e => {
console.log(e.target.options);
const { options } = e.target;
const value = [];
for (let i = 0, l = options.length; i < l; i++) {
if (options[i].selected) {
value.push(options[i].value);
}
}
this.setState({
job: { ...this.state.job, services: value }
});
};
<select
multiple={true}
value={this.state.job.services}
onChange={this.handleJobsDropDown}
>
<option value="paid">Paid Serv</option>
<option value="free">Free Serv</option>
<option value="chain">Chain Serv</option>
<option value="repeat">Rpt Serv</option>
</select>
I have a set of object array like this:
[ProductDetails(name: "Tai Tou Choy",
productDescription: "",
deliveryTime: "24 hours",
img1: "https://api.com.my/images/data/4983-img1-1463122485.jpg",
thumbImg1: "https://api.com.my/images/data/thumbs/4983-img1-1463122485.jpg",
img2: "",
thumbImg2: "",
img3: "",
thumbImg3: "",
videoLink: "",
sku: "0000000004983",
relatedProduct: "",
priceOption: [PriceOption(id: 9931,
label: "500g",
price: "4.56",
promo: "0",
quantity: 999)],
deliveryZone: [DeliveryZone(zone: "3")],
deliveryZoneName: [DeliveryZoneName(zoneName: "Within Klang Valley")],
qrCode: "4983"),
ProductDetails(name: "Penguin Asam Jawa",
productDescription: "",
deliveryTime: "24 hours",
img1: "https://api.com.my/images/data/1004-img1.jpg",
thumbImg1: "https://api.com.my/images/data/thumbs/1004-img1.jpg",
img2: "",
thumbImg2: "",
img3: "",
thumbImg3: "",
videoLink: "",
sku: "0000000001004",
relatedProduct: "",
priceOption: [PriceOption(id: 6971,
label: "1 kg",
price: "4.80",
promo: "0",
quantity: 864)],
deliveryZone: [DeliveryZone(zone: "3")],
deliveryZoneName: [DeliveryZoneName(zoneName: "Within Klang Valley")],
qrCode: "1004")]
I wanted to do price sorting from above the arrays, which the PriceOption array is store inside the main array as an object array too. How do i do sorting from PriceOption? I try to do it in this way :
for i in self.productList{
i.priceOption.sortInPlace{
$0.price.localizedCaseInsensitiveCompare($1.price) == NSComparisonResult.OrderedDescending
}
}
Which return an error "Cannot use mutating member on immutable value :'i' is a 'let' constant."
How to do this?
This how I solve issue that you present. I am using sorted method of the array class.
Solution:
self.productList.sorted{ Float($0.priceOption.first!.price)! > Float($1.priceOption.first!.price)! }
Try this
for i in self.productList {
i.priceOption.sort { $0.price < $1.price } }
The answer for swift 3 is as following
Ascending:
self.productList = self.productList.sorted(by:
{(first: ProductDetails, second: ProductDetails) -> Bool in
first.price > second.price
}
)
Descending:
self.productList = self.productList.sorted(by:
{(first: ProductDetails, second: ProductDetails) -> Bool in
first.price > second.price
}
)