I've made a method to split address line into separate distinct categories like Region, City, Street and House which are represented by a single class. It follows relatively simple structure.
Address useOther(string Casual, string Other)
{
Address
address = new Address();
List<string>
split = new List<string>();
char[]
separator = { ',' };
split.AddRange(
Casual.Split(
separator,
StringSplitOptions.RemoveEmptyEntries));
split.AddRange(
Other.Split(
separator,
StringSplitOptions.RemoveEmptyEntries));
// Initialize parameters
split = RemoveBannedTokens(split);
for (int i = 0; i < split.Count; i++)
{
(address.Region, split[i]) = findRegionByName(split[i]);
if (address.Region != null)
{
split[i] = split[i].Replace(address.Region.Name, "");
break;
}
}
if (address.Region == null)
{
address.Region = new Region(region);
}
split = ClearSplit(split);
// Finding region
for (int i = 0; i < split.Count; i++)
{
(address.City, split[i]) = findSityByName(split[i]);
if (address.City != null)
{
split[i] = split[i].Replace(address.City.Name, "");
break;
}
}
if (address.City == null)
{
for (int i = 0; i < split.Count; i++)
{
(address.City, split[i]) = findCityByName(split[i], false);
if (address.City != null)
{
split[i] = split[i].Replace(address.City.Name, "");
break;
}
}
}
if (address.City == null)
return address;
split = ClearSplit(split);
// Finding city
for (int i = 0; i < split.Count; i++)
{
(address.Street, split[i]) = findStreetByName(split[i], address.City);
if (address.Street != null)
{
split[i] = split[i].Replace(address.Street.Name, "");
break;
}
}
if (address.Street == null &&
(address.Region.Code.Replace("/", "") +
address.City.Code.Replace("/", "")).Length != 13)
return address;
split = ClearSplit(split);
//Finding street
int
cityIndex = address.City.Index,
streetIndex = address.Street.Index;
for (int i = 0; i < split.Count; i++)
{
split[i] = split[i].Replace("б/н", "");
}
address.House = findNumbers(split.ToArray(), cityIndex, streetIndex);
return address;
}
If you can see repetition goes like this
for (int i = 0; i < split.Count; i++)
{
(address.Something, split[i]) = findSomethingByName(split[i]);
if (address.Something != null)
{
//do this thing
break;
}
}
if (address.Something == null)
//try other thing
split = ClearSplit(split);
I want to avoid this repetition and have something of an array or foreach loop but couldn't find a clear way of making an array with reference values or a foreach reference loop that would work with null values properly. I have thought about making a function with specified inputs and outputs but decide it would only harm ability to read my code, which I'm trying to improve here.
After some thinking and looking on how I could manage this, I have decided to follow JAlex advise. For now I don't think this change is necessary, so I leave it be for now. What I will do is I would try make this more readable by using additional spaces and comments. As of for now my method looks something like this (after a bit of tweaking here and there) and I'm more or less happy with how readable it is
Address useOther(string Casual, string Other)
{
Address address =
new Address();
//Initialize address
List<string> split =
new List<string>();
char[] separator =
{
','
};
//Initialize split and separators
split.AddRange(Casual.Split(separator));
split.AddRange(Other .Split(separator));
RemoveBannedTokens(ref split);
//Fill split
for (int i = 0; i < split.Count; i++)
{
(address.Region, split[i]) =
findRegionByName(split[i]);
if (address.Region != null)
break;
}
//Trying to find region
if (address.Region == null)
address.Region = new Region(region);
//If Region is not found
ClearSplit(ref split);
//Get rid of empty strings
for (int i = 0; i < split.Count; i++)
{
(address.City, split[i]) =
findSityByName(split[i]);
if (address.City != null)
break;
}
//Trying to find city
if (address.City == null)
{
for (int i = 0; i < split.Count; i++)
{
(address.City, split[i]) =
findSityByName(split[i], false);
if (address.City != null)
break;
}
}
//Trying to find city with additional params
if (address.City == null)
return address;
//If City is not found
ClearSplit(ref split);
//Get rid of empty strings
for (int i = 0; i < split.Count; i++)
{
(address.Street, split[i]) =
findStreetByName(split[i], address.City);
if (address.Street != null)
break;
}
//Trying to find street
string code =
address.Region.Code.Replace("/", "") +
address.City.Code .Replace("/", "");
//Initialize code
if (address.Street == null && code.Length != 13)
return address;
//If Street is not found and address is not complete
ClearSplit(ref split);
//Finding street
address.House = findNumbers(split);
//Trying to find house
return address;
}