潜在的重复检测,3级严重程度

我想制作一个程序,检测潜在的重复级别为3级。 让我考虑一下我的数据只有两列,但是数千行。 第二列中的数据仅用逗号分隔。 数据示例:

Number | Material 1 | helmet,valros,42 2 | helmet,iron,knight 3 | valros,helmet,42 4 | knight,helmet 5 | valros,helmet,42 6 | plain,helmet 7 | helmet, leather 

我的3个水平是:

非常高: A,B,C A,B,C

高: A,B,C B,C,A

所以: A,B,C A,B

到目前为止我只能做到第一级,我不知道如何做第二和第三级。

我试过了

 Sub duplicates_separation() Dim duplicate(), i As Long Dim delrange As Range, cell As Long Dim shtIn As Worksheet, shtOut As Worksheet Set shtIn = ThisWorkbook.Sheets("input") Set shtOut = ThisWorkbook.Sheets("output") x = 2 y = 1 Set delrange = shtIn.Range("b1:b10000") 'set your range here ReDim duplicate(0) 'search duplicates in 2nd column For cell = 1 To delrange.Cells.Count If Application.CountIf(delrange, delrange(cell)) > 1 Then ReDim Preserve duplicate(i) duplicate(i) = delrange(cell).Address i = i + 1 End If Next 'print duplicates For i = UBound(duplicate) To LBound(duplicate) Step -1 shtOut.Cells(x, 1).EntireRow.Value = shtIn.Range(duplicate(i)).EntireRow.Value End Sub 

程序检测到的重复项

 3 | valros,helmet,42 5 | valros,helmet,42 

我期望的是:

 Number | Material 1 | helmet,valros,42 3 | valros,helmet,42 5 | valros,helmet,42 4 | knight,helmet 2 | helmet,iron,knight 

我有一个想法来检测重复lv 2,但我认为这将是如此复杂,使程序缓慢。

  1. 将第2列转换为“text to columns”命令的列
  2. 从A到Zsorting(按字母顺序)
  3. 连接列
  4. 在检测重复的lv 1中做检测

有没有办法检测第二和第三级重复?


UPDATE

昨天我去朋友家咨询了这个问题,但是他的解决方法是用JAVA语言。>我不明白

 public class ali { static void sPrint(String[] Printed) { for (int iC = 0; iC < Printed.length; iC++) { System.out.print(String.valueOf(Printed[iC]) + " | "); } System.out.println(); } public static void main(String Args[]) { int defaultLength = 10; int indexID = 0; int indexDesc = 1; String[] DETECTORP1 = new String[defaultLength]; String[] DETECTORP2 = new String[defaultLength]; String[] DETECTORP3 = new String[defaultLength]; String[] DETECTORP4 = new String[defaultLength]; String[][] theString = new String[5][2]; theString[0] = new String[]{"1", "A, B, C, D"}; theString[1] = new String[]{"2", "A, B, C, D"}; theString[2] = new String[]{"3", "A, B, C, D, E"}; theString[3] = new String[]{"4", "A, B, D, C, E"}; theString[4] = new String[]{"5", "A, B, D, C, E, F"}; int P1 = 0; int P2 = 0; int P3 = 0; int P4 = 0; for (int iC = 0; iC < theString.length; iC++) { System.out.println(theString[iC][indexID] + " -> " + theString[iC][indexDesc]); } for (int iC = 0; iC < theString.length; iC++) { int LEX; String theReference[] = theString[iC][indexDesc].replace(",", ";;").split(";;"); for (int iD = 0; iD < theString.length; iD++) { if (iC != iD) { String theCompare[] = theString[iD][1].replace(",", ";;").split(";;"); if (theReference.length == theCompare.length) { LEX=0; int theLength = theReference.length; for (int iE = 0; iE < theLength; iE++) { if (theReference[iE].equals(theCompare[iE])) { LEX += 1; } } if (LEX == theLength) { DETECTORP1[P1] = theString[iC][indexID] + " WITH " + theString[iD][indexID]; P1 += 1; } else { LEX = 0; for (int iF = 0; iF < theReference.length; iF++) { for (int iG = 0; iG < theCompare.length; iG++) { if (theReference[iF].equals(theCompare[iG])) { LEX += 1; break; } } } if (LEX == theReference.length) { DETECTORP2[P2] = theString[iC][indexID] + " WITH " + theString[iD][indexID]; P2 += 1; } } } else { LEX = 0; if (theReference.length > theCompare.length) { for (int iF = 0; iF < theReference.length; iF++) { for (int iG = 0; iG < theCompare.length; iG++) { if (iG == iF) { if (theReference[iF].equals(theCompare[iF])) { LEX += 1; break; } } } } if (LEX <= theReference.length && LEX >= theCompare.length) { DETECTORP3[P3] = theString[iC][indexID] + " WITH " + theString[iD][indexID]; P3 += 1; } } else { LEX =0; for (int iF = 0; iF < theCompare.length; iF++) { for (int iG = 0; iG < theReference.length; iG++) { if (iG == iF) { if (theCompare[iF].equals(theReference[iF])) { LEX += 1; // System.out.println(theReference[iG] + "==" + theCompare[iG]); break; } } } } if (LEX <= theCompare.length && LEX >= theReference.length) { DETECTORP3[P3] = theString[iC][indexID] + " WITH " + theString[iD][indexID]; P3 += 1; } } } } } } sPrint(DETECTORP1); sPrint(DETECTORP2); sPrint(DETECTORP3); } } 

如何在VBA中做到这一点?

真的,这取决于你想如何定义“严重程度”。 这里有一个办法,不一定是最好的:使用Levensthein距离。

用一个单字符的属性符号表示每个项目,例如

 H helmet K knight I iron $ Leather ^ Valros ╔ Plain ¢ Whatever etc. 

然后将您的材料列表转换为包含代表这些属性的字符序列的string:

 HIK = helmet,iron,knight ¢H = plain,helmet 

然后计算这两个string之间的Levenshtein距离。 这将是你的“严重程度”。

 Debug.Print LevenshteinDistance("HIK","¢H") 'returns 3 

Levenshtein距离的两个实现在Wikipedia中显示。 事实上,你是幸运的:在StackOverflow上的人将其移植到VBA 。

在下面的评论部分,你说你不喜欢用一个字符来表示每个可能的属性。 很公平; 我同意这有点傻。 解决方法:实际上,可以调整Levenshtein距离algorithm,使其不是查看string中的每个字符,而是查看数组中的每个元素,然后根据该比较进行比较。 我展示了如何在你的后续问题的答案中做出这个改变。