已回答 是对象'SortedSet'是否打算用于不是数组的原始变量?

已加入
2020年2月15日
留言内容
16
编程经验
1-3
例如:
静态SortedSet<int[]> stl = new SortedSet<int[]>();
如果我尝试将第二个成员添加为int数组,则会收到一个错误,提示我应实现IComparable接口:
(在图像1下方出现错误的屏幕截图)
我的问题是使用带有int数组的SortedSet完全正确吗?还是根本没有原始类型的数组?
因此,它应该工作,所以我应该如何使用类型变量来实现此接口?相反,我应该构建一个特定的对象吗?
无论如何,我发现了另一种与HashSet一起使用的方法,该方法与SortedSet的逻辑相同,可以防止重复但存在问题
当我有超过500,000个器官时,它并不会真正检查数组中是否存在添加的器官(图2下的屏幕截图出现)
这意味着它保留重复项
毕竟,当器官数量很大时,如何避免重复?
1596052020755.png
1596052520569.png
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,607
地点
弗吉尼亚州切萨皮克
编程经验
10+
将来,请在代码标签而不是屏幕快照中发布您的代码。

另外,您还可以通过选择以下内容来复制并粘贴例外内容"将异常详细信息复制到剪贴板"
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,607
地点
弗吉尼亚州切萨皮克
编程经验
10+
If the type T you are passing in does not implement IComparable, then you can provide an IComparer<T>. For example:
C#:
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        var hashSet = new SortedSet<int[]>(Comparer<int[]>.Create(CompareIntArrays));

        int x = CompareIntArrays(null, new[] { 2 });

        hashSet.Add(new[] { 1, 2, 3 });
        hashSet.Add(new[] { 4, 5, 6 });

        int CompareIntArrays(int [] a, int [] b)
        {
            if (a == null && b == null)
                return 0;
            if (a != null && b == null)
                return 1;
            if (a == null && b != null)
                return -1;

            var comp = a.Length - b.Length;
            if (comp != 0)
                return comp;

            return a.Zip(b, (l, r) => l - r)
                    .TakeWhile(c => c == 0)
                    .FirstOrDefault();
        }
    }
}

Zip() 将从每个集合中获取一个值并将其传递给函数。在上述情况下,我的lambda会计算两个值之间的差值。
TakeWhile() 以上将跳过相等的前导值对。
FirstOrDefault() 将返回第一个非零增量,或者如果跳过所有值对,则将返回默认整数值0,该值恰好是表示两个对象相等的值。
 

羊皮

知名会员
已加入
2018年9月5日
留言内容
1,982
编程经验
10+
我希望使用列表和排序列表。但是既然你不是...

这是您的选项,您可以像下面的示例一样添加IComparable:

或重新声明您的数组值:
清除您的设置并重新添加阵列
C#:
            sset.Add(new int[] { 1, 2, 3, 4 });
            sset.Clear();
            sset.Add(new int[] { 1,2,3,4,5,6,7,8 });
或使用列表转换数据以追加数组。像这个例子:
C#:
        public SortedSet<int[]> sset = new SortedSet<int[]>();

        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            sset.Add(new int[] { 1, 2, 3, 4 });
            List<int> updatedLst = new List<int>();
            SortedSet<int[]>.Enumerator x = sset.GetEnumerator();
            while (x.MoveNext())
            {
                if (x.Current != null)
                {
                    x.Current.ToList().ForEach((int value) =>
                    {
                        updatedLst.Add(value);
                        Debug.WriteLine($"{value} was added to the new list");
                    });
                }
            }
            updatedLst.AddRange(new int[] { 5,6,7,8,9 });
            sset.Clear();
            sset.Add(updatedLst.ToArray());

            /* Now lets print your new values to the debug window */
            int iter = -1;
            foreach (int[] intarr in sset)
            {
                foreach (int i in intarr)
                {
                    iter++;
                    Debug.WriteLine($"The number at index {iter} is : {i}");
                }
            }
        }
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,607
地点
弗吉尼亚州切萨皮克
编程经验
10+
Unfortunately, that is not what the OP is looking for. They are using an int [] to store a single lotto number guess. Multiple int [] are multiple guesses. They are trying to use the set to store multiple guesses. So the code above which just merges the new guesses with the existing entry won't let him/her later determine if they have a winning guess or not.
 

羊皮

知名会员
已加入
2018年9月5日
留言内容
1,982
编程经验
10+
对不起,如果我误会了。

一定是因为令人讨厌的屏幕截图使我相信他想将更多项目添加到它们已经存储在集合中的int []数组中。它一定以某种方式淹没了文本并使我陷入了我的假设。大声笑我不好,这是漫长的一天。 。 。 。

使用Hashset或Dictionary有什么问题?哈希集可以实时确定集合中是否存在特定项目,而不管其中的项目数量如何。这可能是最好的选择。两者都可以防止重复。
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,607
地点
弗吉尼亚州切萨皮克
编程经验
10+
And he is using a HashSet<T> in his second screenshot as his solution to his problem. If only he had actually used code tags instead of screenshots, this would be so much easier to read and understand.
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,607
地点
弗吉尼亚州切萨皮克
编程经验
10+
Unfortunately, the HashSet<T> uses the hash code of the 参考,而不是值。所以下面的代码打印出来"False":
C#:
var hashSet = new HashSet<int[]>();
hashSet.Add(new[] { 1, 2, 3 });
Console.WriteLine(hashSet.Contains(new[] { 1, 2, 3 }));

He's going to have to pass in an IComparer<T> into the constructor for the HashSet<T> like for the SortedSet<T> if he wants to compare values in the array rather than references to arrays.
 

羊皮

知名会员
已加入
2018年9月5日
留言内容
1,982
编程经验
10+
做这样的事情,但是我强烈建议在这里添加消息泵,我实在太累了,现在不能实现它:
C#:
        public HashSet<string> hs = new HashSet<string>();
        public StringBuilder strBuilder = new StringBuilder();
        public char[] numChars = "0123456789".ToCharArray();
        public readonly ThreadLocal<Random> randGenerator = new ThreadLocal<Random>(() => new Random());

并将其粘贴在方法中:
C#:
            for (int i = hs.Count; i < 20000000; i++)
            {
                int @int = randGenerator.Value.Next(0, 10);
                if (strBuilder.Length != 10)
                    strBuilder.Append(numChars[@int]);
                else
                {
                    hs.Add(strBuilder.ToString());
                    Debug.WriteLine($"New lotto number added : {strBuilder}");
                    strBuilder.Clear();
                }
            }
            Debug.WriteLine($"Hashset items has {hs.Count} items");
 

羊皮

知名会员
已加入
2018年9月5日
留言内容
1,982
编程经验
10+
为我工作,我收到了大约60000个条目,并且处理得很好。为什么您会有超过500K的问题,这可能不取决于哈希表。哈希集并不关心其中包含多少项,因为它知道它是否已经有一项,因此,如果有则不会添加。
 

跳伞者

工作人员
已加入
2019年4月6日
留言内容
2,607
地点
弗吉尼亚州切萨皮克
编程经验
10+
有趣的方法...从强类型转变为字符串类型。简化事务。为了简单起见,牺牲内存是所有软件工程师都必须平衡的。

So instead of writing about 20 lines of new code -- new code that may have bugs -- to do array comparisons, use the built in string comparisons (that should have been debugged by Microsoft and has been road tested by millions of people) and use on average 6 bytes per lotto number column vs. the fixed 4 bytes per lotto number column of the int []. So with 6 lotto numbers, the string would on average use 38 bytes (4 byte length + 6 * 2 digits * 2 byte Unicode character + 5 * 2 Unicode character for space between numbers) vs the array using 28 bytes (4 byte length + 6 * 4 byte integer). 500K lotto guess comes out to be 19MB vs 15MB. What's an extra 4MB when you have several GB of RAM? Memory is cheap, right? Reliability is more expensive.
 
已加入
2020年2月15日
留言内容
16
编程经验
1-3
这是询问者的代码:
C#:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace LotoHashSet
{
    class Program
    {

        static HashSet<int[]> hashLoto = new HashSet<int[]>();
        const int SIZE = 1000000;
   

        static void Main(string[] args)
        {

            AddGusses();
        }
    
         

        static void AddGusses()
        {

            var rand = new Random();
            for (int i = 0; i < SIZE; i++)
            {
                var arrTemp = new int[7];
                for (int j = 0; j < arrTemp.Length - 1; )
                {
                    int num = rand.Next(1, 38);

                    if (!arrTemp.Contains(num))
                    {
                        arrTemp[j] = num;
                        j++;
                    }
                }

                Array.Sort(arrTemp);
                arrTemp[0] = rand.Next(1, 8);
                hashLoto.Add(arrTemp);
           
            }
        }
    }
}
 
由主持人最后编辑:
最佳 底部