C# 如何修复我的LINQ以从字符串中的列表中正确查找字符串?
几个小时前,我已经在和LINQ做斗争,LINQ应该从地址列表中的对象列表中查找城市 我有一个C# 如何修复我的LINQ以从字符串中的列表中正确查找字符串?,c#,list,linq,C#,List,Linq,几个小时前,我已经在和LINQ做斗争,LINQ应该从地址列表中的对象列表中查找城市 我有一个CityModel对象列表,其中: public class CityModel { public string City { get; set; } public char CountryChar { get; set; } } 和AddressModel对象列表: public class AddressModel { publ
CityModel
对象列表,其中:
public class CityModel
{
public string City { get; set; }
public char CountryChar { get; set; }
}
和AddressModel
对象列表:
public class AddressModel
{
public string Address { get; set; }
public char CountryChar { get; set; }
}
addressesM.Add(new AddressModel()
{
Address = "#20-06, gateway east, 152, beach road, singapore 189721",
CountryChar = 's'
});
addressesM.Add(new AddressModel()
{
Address = "01-01, 8, anthony road, singapore 229957",
CountryChar = 's'
}); //note: Anthony
在这两种情况下,CountryChar
都是属于城市
或地址
属性的国家的第一个字母。所有字符串和字符都是从ToLower()
解析的,因此它们都是小写的
CityModel
对象的示例:
cities.Add(new CityModel()
{
City = "singapore",
CountryChar = 's'
}); //Singapore in singapore
cities.Add(new CityModel()
{
City = "anthony",
CountryChar = 'u'
}); //Anthony in United States
AddressModel
对象的两种情况:
public class AddressModel
{
public string Address { get; set; }
public char CountryChar { get; set; }
}
addressesM.Add(new AddressModel()
{
Address = "#20-06, gateway east, 152, beach road, singapore 189721",
CountryChar = 's'
});
addressesM.Add(new AddressModel()
{
Address = "01-01, 8, anthony road, singapore 229957",
CountryChar = 's'
}); //note: Anthony
我的LINQ的想法是在每个AddressModel
对象中查找是否有任何城市是我的Address
属性的子字符串。如果是,则验证AddressModel的CountryChar
是否与CityModel的CountryChar
匹配
我的林克:
foreach (AddressModel address in addressesM)
{
string city = "xxx";
i++;
Console.WriteLine(i + " z " + addresses.Count());
CityModel tocompare = cities.Where(collectionOfCities => address.Address.IndexOf(collectionOfCities.City) >= 0 &&
(address.Address[address.Address.IndexOf(collectionOfCities.City) - 1] == ' ' ||
address.Address[address.Address.IndexOf(collectionOfCities.City) - 1] == ',') &&
(address.Address[address.Address.IndexOf(collectionOfCities.City) + collectionOfCities.City.Length] == ' ' ||
address.Address[address.Address.IndexOf(collectionOfCities.City) + collectionOfCities.City.Length] == ',') &&
collectionOfCities.CountryChar == address.CountryChar).FirstOrDefault();
if (tocompare != null)
{
TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;
tocompare.City = textInfo.ToTitleCase(tocompare.City);
city = tocompare.City;
}
output.Add(city);
}
对于我的AddressModel
LINQ的第一种情况,它工作得很好。当我的第二个AddressModel
里面有一个单词“Anthony”时,问题就出现了,还有一个城市叫Anthony
。在这种情况下,在检查“Anthony”的其余LINQ条件后,它将添加到我的输出
“xxx”字符串,并移动到列表中的下一个地址模型
我不知道在“安东尼”城市失败后该如何做,该计划将测试列表中的其他城市?
编辑:
某些地址可能有包含数字和大写字母的邮政编码,例如:
上海市浦东新区财伦路1690号1-3楼7座,
201203,中国
蒙大拿州鲁西诺镇安托万1号码头6号1楼,邮编98012
卡罗,塞德克斯,摩纳哥
加利福尼亚州西湖村多尔大道1号,邮编:91362-7300,
美国
Gratsos大厦,15号,Eleftheriou Venizelou街,105 64
雅典,希腊
一些城市名称可能有1个以上的单词,例如:
鱼鹰
巴拿马城
拉凡尔纳
首先,让我们组织城市;假设(City,CountryChar)
组合是唯一的,我们可以构建一个字典:
List<CityModel> cities = ...
Dictionary<(string city, char country), CityModel> citiesDict = cities
.ToDictionary(item => (item.City, item.CountryChar),
item => item);
或更宽松(任何名称将返回“网关”
,“东”
,“海滩”
,“道路”
,“新加坡”
)实施:
IEnumerable<string> CityNames(string address) {
return Regex
.Matches(address, @"\b[a-z]+\b", RegexOptions.IgnoreCase)
.Cast<Match>()
.Select(match => match.Value);
}
编辑:这里的主要困难是提取潜在的城市名称(一般情况下是自然语言处理…)。如果您能保证地址部分(街道、城市、国家等)用逗号分隔,
我们可以尝试拆分:
IEnumerable<string> CityNames(string address) {
return address
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(item => Regex.Replace(item.Trim(), @"\s+", " ").ToLower())
.Where(item => !string.IsNullOrEmpty(item));
}
您的解决方案非常有效,谢谢。我想我会喜欢林克的。唯一的问题是当我试图解析包含多个单词的城市名称时。例如新新加坡。如果将地址
字符串拆分为单独的单词,则会失败。我不确定在这种情况下如何分割地址(更新的问题)。请注意,地址字符串可能包含带有数字和字母的邮政编码。@bakunet:当然,您可以拆分(如果您可以保证地址部分由,
正确分隔,并且您没有,比如“37 Nevsky pospect Saint Petersburg”
),实际上,经过编辑后,它工作得非常好。斯帕西巴!
IEnumerable<string> CityNames(string address) {
return address
.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(item => Regex.Replace(item, "[0-9]+", ""))
.Select(item => Regex.Replace(item.Trim(), @"\s+", " ").ToLower())
.Where(item => !string.IsNullOrEmpty(item));
}