寻找一些帮助来解决这个问题。我有两个名字阵列。我需要做的是对它们进行冒泡排序(我已经完成了,请参见下面的代码),并使用前两个数组中的值填充第三个数组,省略重复项,而不是排序第三个数组。下面是我的示例代码,它完全适用于我正在做的事情,除了我需要使用循环来填充第三个数组(逻辑练习)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MergeArray
{
class Program
{
static void Main(string[] args)
{
string[] names1 = { "Bob", "John", "Bill", "Sandy", "Betty", "Bart", "Patty" };
string[] names2 = { "Andy", "Chris", "Bill", "Walter" };
string[] names3 = new string[names1.Length + names2.Length];
string temp;
foreach (string i in names1)
{
for (int j = 0; j < names1.Length - 1; j++)
{
if (String.Compare(names1[j], names1[j+1]) > 0)
{
temp = names1[j];
names1[j] = names1[j + 1];
names1[j + 1] = temp;
}
}
}
foreach (string i in names2)
{
for (int j = 0; j < names2.Length - 1; j++)
{
if (String.Compare(names2[j], names2[j + 1]) > 0)
{
temp = names2[j];
names2[j] = names2[j + 1];
names2[j + 1] = temp;
}
}
}
names1.CopyTo(names3, 0);
names2.CopyTo(names3, names1.Length);
Console.WriteLine(String.Join(Environment.NewLine, names3.Distinct().ToArray()));
Console.ReadLine();
}
}
}
最后,这段代码完成了我需要做的事情,第三个阵列填充了“Bart,Betty,Bill,Bob,John,Patty,Sandy,Andy,Chris,Walter”。它没有填写重复的“Bill”,它只是将两个数组加在一起,而不是排序第三个(这是我需要做的)。我需要帮助的是将我填充第三个数组的部分转换为循环而不是:
names1.CopyTo(names3, 0);
names2.CopyTo(names3, names1.Length);
Console.WriteLine(String.Join(Environment.NewLine, names3.Distinct().ToArray()));
请帮助我了解我需要在这里做些什么。
答案 0 :(得分:1)
哦linq
的力量!
string[] names1 = { "Bob", "John", "Bill", "Sandy", "Betty", "Bart", "Patty" };
string[] names2 = { "Andy", "Chris", "Bill", "Walter" };
string[] names3 = names1.Union(names2).Distinct().ToArray();
答案 1 :(得分:1)
正如ryanyuyu建议的那样,使用修改后的合并操作 这将在您对它们进行排序后进行。
int m = 0;
int n = 0;
while ((m < names1.Count) && (n < names1.Count))
{
int comparison = String.Compare(names1[m], names2[n]);
if (comparison < 0) // names1[m] is before names2[n]
{
names3.Add(names1[m]);
m = m + 1;
}
else if (comparison > 1) //names2[n] is before names1[m]
{
names3.Add(names2[n]);
n = n + 1;
}
else //names1[m] is equal to names2[n], only add one.
{
names3.Add(names1[m]);
m = m + 1;
n = n + 1;
}
}
//either names1 or names2 ran out of entries. fill names3 with whatever is left
while (m < names1.Count)
{
names3.Add(names1[m]);
m = m + 1;
}
while (n < names2.Count)
{
names3.Add(names2[n]);
n = n + 1;
}
如果原始数组本身可能包含重复项,则可以使用HashSet跟踪已添加的值。
List<string> names1 = new List<string>();
List<string> names2 = new List<string>();
List<string> names3 = new List<string>();
var included = new HashSet<string>();
int m = 0;
int n = 0;
while ((m < names1.Count) && (n < names1.Count))
{
int comparison = String.Compare(names1[m], names2[n]);
if (comparison < 0)
{
if(included.Add(names1[m]))
{
names3.Add(names1[m]);
}
m = m + 1;
}
else if (comparison > 1)
{
if (included.Add(names2[n]))
{
names3.Add(names2[n]);
}
n = n + 1;
}
else
{
names3.Add(names1[m]);
m = m + 1;
n = n + 1;
}
}
while (m < names1.Count)
{
if (included.Add(names1[m]))
{
names3.Add(names1[m]);
}
m = m + 1;
}
while (n < names2.Count)
{
if (included.Add(names2[n]))
{
names3.Add(names2[n]);
}
n = n + 1;
}
当然,此时您也可以将names3
设为HashSet
并跳过额外的检查。保持included
分开的唯一好处是names3
保留了排序顺序。如果names3本身是HashSet并且你在最后做了names3.ToArray(),则无法保证这是真的。
答案 2 :(得分:1)
假设您的冒泡排序成功对元素进行排序,您可以使用修改后的合并操作将最终数组放在一起。基本上,合并需要两个排序的数组,并通过比较每个数组的“顶部”元素并将其移动到复合数组来将它们放在一起。
在执行此操作时,您只需要检查重复项。并且由于您的数组都已排序,所有重复项将聚合成组,因此您只需要跟踪最近的重复项。
这样的事情(非常详细且评论很多)可以起作用:
public static string[] MergeNoDuplicates(string[] left, string[] right)
{
var mergedArray = new string[left.Length + right.Length];
//since the arrays are sorted, we only need to keep track of the most recent duplicate
string duplicateChecker = null;
int mergeIndex = 0;
int l = 0; //index for left array
int r = 0; //index for right array
//while there are more element in at least one of the two arrays
bool leftHasElements = l < left.Length;
bool rightHasElements = r < right.Length;
while (leftHasElements && rightHasElements)
{
string leftString = left[l];
string rightString = right[r];
int comparisonResult = leftString.CompareTo(rightString);
if (comparisonResult < 0) //left string comes before right string
{
//not a duplicate
if (leftString.CompareTo(duplicateChecker) != 0)
{
mergedArray[mergeIndex] = leftString;
mergeIndex++;
duplicateChecker = leftString;
}
//regardless of whether it's a duplicate move onto the next element
l++;
}
else if (comparisonResult > 0) //right string comes before left
{
if (rightString.CompareTo(duplicateChecker) != 0)
{
mergedArray[mergeIndex] = rightString;
mergeIndex++;
duplicateChecker = rightString;
}
r++;
}
else //comparisonResult by default == 0
{
//since they are the same string, just insert one (if needed), but increment both arrays
if (leftString.CompareTo(duplicateChecker) != 0)
{
mergedArray[mergeIndex] = leftString;
mergeIndex++;
duplicateChecker = leftString;
}
l++;
r++;
}
leftHasElements = l < left.Length;
rightHasElements = r < right.Length;
}
//now at least one of the arrays is empty, so add all of the remaining
//non-duplicate elements of the other to the array
//if either is false, the loop won't execute in the first place
while (leftHasElements)
{
string leftString = left[l];
if (leftString.CompareTo(duplicateChecker) != 0)
{
mergedArray[mergeIndex] = leftString;
mergeIndex++;
duplicateChecker = leftString;
}
l++;
leftHasElements = l < left.Length;
}
while (rightHasElements)
{
string rightString = right[r];
if (rightString.CompareTo(duplicateChecker) != 0)
{
mergedArray[mergeIndex] = rightString;
mergeIndex++;
duplicateChecker = rightString;
}
r++;
rightHasElements = r < right.Length;
}
//now remove null elements (if needed) and return
//alternatively, just use LINQ's TakeWhile and ToArray
if (mergeIndex == mergedArray.Length)
return mergedArray;
var returnedArray = new string[mergeIndex];
Array.Copy(mergedArray, returnedArray, mergeIndex);
return returnedArray;
}
答案 3 :(得分:0)
我建议使用&#34;区别&#34;
复制到列表&lt;&gt;使用&#34; AddRange()&#34;添加第二个数组。
使用&#34; Distinct()&#34;消除重复,
最后,将列表转换回数组。
实施例
List<string> myList = myArray.Cast<string>().ToList();
myList.AddRange(mySecondArray);
string[] myNewArray = myList.Distinct().toArray();
答案 4 :(得分:0)
为什么不:
List<string> names = new List<string>();
names.AddRange(names1);
names.AddRange(names2);
names.Sort();
string[] names3 = names.Distinct().ToArray();
答案 5 :(得分:0)
你可以使用.Union:
string[] names1 = { "Bob", "John", "Bill", "Sandy", "Betty", "Bart", "Patty" };
string[] names2 = { "Andy", "Chris", "Bill", "Walter" };
string[] names3 = names1.Union(names2).ToArray();
答案 6 :(得分:0)
我会使用这样的循环:
int names1I = 0;
int names2I = 0;
for(int i = 0; names1I < names1.Length && names2I < names2.Length; i++)
{
while(names1I < names1.Length && names3.Contains(names1[names1I]))
names1I++;
while(names2I < names2.Length && names3.Contains(names2[names2I]))
names2I++;
if(names1I == names1.Length) //if you have already reached the end of array 1, you have to use array 2
names3[i] = names2[names2I++];
else if(names2I == names2.Length) //if you have already reached the end of array 2, you have to use array 1
names3[i] = names1[names1I++];
else //else take the smaller of the 2 possible values
names3[i] = (names1[names1I] <= names2[names2I]) ? names1[names1I++] : names2[names2I++];
}