我需要比较一维数组,因为我需要将数组的每个元素与每个其他元素进行比较。该数组包含从最长到最短排序的字符串列表。数组中没有2个项目相同,但是会有相同长度的项目。目前我正在进行N *(N + 1)/ 2比较(127.8亿),我正在努力减少所有比较的数量。
我已经实现了一个功能,基本上说:如果字符串长度不同超过x%,那么不要打扰他们不相等,而他下面的其他人也不相等,所以只是打破循环,转到下一个元素。
我目前正试图通过这样说来进一步减少这一点:如果元素A匹配元素C和D,那么它可以理解元素C和D也会匹配,所以不要费心检查它们(即跳过该操作)。这是我所考虑的因为我目前不知道允许我这样做的数据结构。
这里的问题是:有谁知道这样的数据结构?或者有谁知道如何进一步减少我的比较?
我目前的实施估计需要3.5天才能在10小时的时间窗口内完成(也就是说它太长了)而我剩下的唯一选择是减少执行时间,这可能是也可能是不可能的,或者是分配几十个系统的工作量,这可能是不切实际的。
更新:我的不好。将等于的单词替换为与...紧密匹配。我正在计算Levenstein距离
想法是找出数组中是否有其他字符串与数组中的每个元素紧密匹配。输出是密切相关的字符串的数据库映射。
以下是该方法的部分代码。在执行此代码块之前,有代码将项加载到数据库中。
public static void RelatedAddressCompute() {
TableWipe("RelatedAddress");
decimal _requiredDistance = Properties.Settings.Default.LevenshteinDistance;
SqlConnection _connection = new SqlConnection(Properties.Settings.Default.AML_STORE);
_connection.Open();
string _cacheFilter = "LevenshteinCache NOT IN ('','SAMEASABOVE','SAME')";
SqlCommand _dataCommand = new SqlCommand(@"
SELECT
COUNT(DISTINCT LevenshteinCache)
FROM
Address
WHERE
" + _cacheFilter + @"
AND
LEN(LevenshteinCache) > 12", _connection);
_dataCommand.CommandTimeout = 0;
int _addressCount = (int)_dataCommand.ExecuteScalar();
_dataCommand = new SqlCommand(@"
SELECT
Data.LevenshteinCache,
Data.CacheCount
FROM
(SELECT
DISTINCT LevenshteinCache,
COUNT(LevenshteinCache) AS CacheCount
FROM
Address
WHERE
" + _cacheFilter + @"
GROUP BY
LevenshteinCache) Data
WHERE
LEN(LevenshteinCache) > 12
ORDER BY
LEN(LevenshteinCache) DESC", _connection);
_dataCommand.CommandTimeout = 0;
SqlDataReader _addressReader = _dataCommand.ExecuteReader();
string[] _addresses = new string[_addressCount + 1];
int[] _addressInstance = new int[_addressCount + 1];
int _itemIndex = 1;
while (_addressReader.Read()) {
string _address = (string)_addressReader[0];
int _count = (int)_addressReader[1];
_addresses[_itemIndex] = _address;
_addressInstance[_itemIndex] = _count;
_itemIndex++;
}
_addressReader.Close();
decimal _comparasionsMade = 0;
decimal _comparisionsAttempted = 0;
decimal _comparisionsExpected = (decimal)_addressCount * ((decimal)_addressCount + 1) / 2;
decimal _percentCompleted = 0;
DateTime _startTime = DateTime.Now;
Parallel.For(1, _addressCount, delegate(int i) {
for (int _index = i + 1; _index <= _addressCount; _index++) {
_comparisionsAttempted++;
decimal _percent = _addresses[i].Length < _addresses[_index].Length ? (decimal)_addresses[i].Length / (decimal)_addresses[_index].Length : (decimal)_addresses[_index].Length / (decimal)_addresses[i].Length;
if (_percent < _requiredDistance) {
decimal _difference = new Levenshtein().threasholdiLD(_addresses[i], _addresses[_index], 50);
_comparasionsMade++;
if (_difference <= _requiredDistance) {
InsertRelatedAddress(ref _connection, _addresses[i], _addresses[_index], _difference);
}
}
else {
_comparisionsAttempted += _addressCount - _index;
break;
}
}
if (_addressInstance[i] > 1 && _addressInstance[i] < 31) {
InsertRelatedAddress(ref _connection, _addresses[i], _addresses[i], 0);
}
_percentCompleted = (_comparisionsAttempted / _comparisionsExpected) * 100M;
TimeSpan _estimatedDuration = new TimeSpan((long)((((decimal)(DateTime.Now - _startTime).Ticks) / _percentCompleted) * 100));
TimeSpan _timeRemaining = _estimatedDuration - (DateTime.Now - _startTime);
string _timeRemains = _timeRemaining.ToString();
});
}
InsertRelatedAddress是一个更新数据库的函数,数组中有500,000个项目。
答案 0 :(得分:1)
行。随着更新的问题,我认为这更有意义。您希望找到Levenshtein距离小于预设距离的字符串对。我认为关键是你不要比较每组字符串,并依靠Levenshtein距离的属性来搜索预设限制内的字符串。答案涉及计算可能变化的树。也就是说,计算距离<1的给定字符串的可能变化。 n并查看是否有任何字符串在您的集合中。我认为如果n很小,这只会更快。
看起来像这里发布的问题:Finding closest neighbour using optimized Levenshtein Algorithm。
答案 1 :(得分:0)
需要更多信息。你期望的结果是什么?你想要计算所有独特的字符串吗?你声明你想看看2个字符串是否相等,如果'它们的长度不同x%,那么就不要打扰它们不等于'。为什么要检查长度约束x%?如果你要检查它们是否相等,它们的长度必须相同。 我怀疑你正在尝试与确定完全匹配略有不同的东西,在这种情况下我需要更多信息。 谢谢 尼尔