【问题标题】:List only contains first two items列表仅包含前两项
【发布时间】:2014-05-05 00:04:32
【问题描述】:

好的,我很确定 isNumber 终于可以工作了。感谢大家的帮助。我想我几乎已经准备好开始真正开始这个项目了。我只是想把头绕在列表上。

我正在做的是尝试一次检查一堆输入(如果它们是数字)并将结果存储在列表中。那样的话,要找出其中一个是否是数字,我只需检查第二个列表中的相应值即可。

所以,我的问题是我清楚地把 3 件东西放在了我的清单中,但是当我打印出项目数时,它总是显示 2。这到底有什么问题?具体来说,为什么 areNumbers 总是返回一个长度为 2 的列表,而我显然让它至少与 numberOfNumbers 一样长?

PS 我知道我的代码看起来还不是很好。我想在了解风格之前先了解基础知识。

    static void Main(string[] args)
    {
        var maybe = new ArrayList(3);
        maybe.Add(100f);
        maybe.Add("not a number");
        maybe.Add(1000);

        Console.WriteLine(areNumbers(maybe).Count);
        Console.ReadLine();
    }
    static ArrayList areNumbers(ArrayList maybeNumbers)
    {
        var theResults = new ArrayList(0);
        var numbersEnumerator = maybeNumbers.GetEnumerator();
        var numberOfNumbers = 0;

        try
        {
            for (; ; )
            {
                numberOfNumbers = numberOfNumbers + 1;
                numbersEnumerator.MoveNext();
                var myIsNumber = isNumber(numbersEnumerator.Current);
                var myAreNumbers = new ArrayList(numberOfNumbers);
                myAreNumbers.Add(theResults);
                myAreNumbers.Add(myIsNumber);
                theResults = myAreNumbers;
            }
        }
        catch (InvalidOperationException)
        {
            return theResults;
        }
    }
    static bool isNumber(object theObject)
    {
        var s = theObject.GetType().ToString().ToUpper();
        Console.WriteLine(s);
        return theObject is int || theObject is Int64 || theObject is float || theObject is double;
    } 

【问题讨论】:

  • 这一行的目的是什么?对于 (; ; ) {
  • 看起来当 MoveNext 失败时 Catch 会抓住它。奇怪,伙计。
  • 您正在向列表中添加三个项目。其中两个可以解释为数字,一个不能。然后打印来自areNumbers 的返回值的计数,并得到 2. 2 个值是数字。这不是你想要的吗?
  • 这是我见过的最糟糕的代码之一。首先,不是使用foreach 来迭代maybeNumbers,而是使用GetEnumerator,一个无限循环,并捕获由'MoveNext()! You can replace all of this mess with a simple foreach` 循环抛出的InvalidOperationException。其次,您将bools 和ArrayLists 混合在ArrayList 中。为什么?
  • 这家伙正在努力学习并寻求建议。鼓励他。

标签: c# list


【解决方案1】:

正如评论者所说,返回值areNumbers 最多将是一个包含 2 个项目的 ArrayList(第一个项目是 0 到 N-2 项目的布尔值的 ArrayList;第二个项目将是一个布尔值第 (N-1) 个值)。如果我正确地单步执行了我脑海中的代码,如果你发送一个空的 ArrayList,你会得到一个空的 ArrayList。

在一项之后:

areNumbers[0]: [] // 空数组列表 areNumbers[1]: 真

后两项:

areNumbers[0]: [[], true] // 在第一项之后 areNumbers[1]: 假

三项后

areNumbers[0]: [[[], true], false] // 在第二项之后 areNumbers[1]: 真

如果您使用第 4 个数字值调用:

areNumbers[0]: [[[[], true], false], true] areNumbers[1]: 真

现在希望您不会陷入泛型和 LINQ 之前的世界......

Where 将根据您的isNumber 函数进行过滤:

var maybeNumbers = new List<object>{ 100f, "not a number", 1000 };
var areNumbers = maybeNumbers.Where(isNumber).ToList();

Assert.AreEqual(2, areNumbers.Count());  //passes!

如果您是 LINQ 之前的用户,请尝试以下操作:

List<object> maybeNumbers = new List<object>();
maybeNumbers.Add(100f);
maybeNumbers.Add("not a number");
maybeNumbers.Add(1000);

List<object> areNumbers = new List<object>();

foreach(object maybe in maybeNumbers)
{
    if (isNumber(maybe))
        areNumbers.Add(maybe);
}

预泛型(可能无法编译...)

ArrayList maybeNumbers = new ArrayList();
maybeNumbers.Add(100f);
maybeNumbers.Add("not a number");
maybeNumbers.Add(1000);

ArrayList areNumbers = new ArrayList();

foreach(object maybe in maybeNumbers)
{
    if (isNumber(maybe))
        areNumbers.Add(maybe);
}

【讨论】:

    【解决方案2】:

    这将遍历一个对象列表并给你一个布尔响应,让你知道它们是否是数字的,我认为这就是你的代码最终所做的。

    var testNumbers = new List<object>();
    testNumbers.Add(15);
    testNumbers.Add("AUUUGHH");
    testNumbers.Add(42);
    
    foreach (var i in testNumbers)
        Console.WriteLine(Microsoft.VisualBasic.Information.IsNumeric(i));
    

    确保添加对 Microsoft.VisualBasic 命名空间的引用以使用 IsNumeric()

    【讨论】:

      【解决方案3】:

      1. 不要依赖 try/catch 来进行正常的代码流。 try/catch 用于捕捉异常情况

      2.为什么需要构建isNumber方法? double.tryParse 或 Convert.ToDouble() 会做类似的事情(谷歌查找差异)

      3.不知道 myAreNumbers 应该做什么,但您基本上是在每次迭代时将一个 bool 和一个列表添加到一个新列表中

      static ArrayList areNumbers(ArrayList maybeNumbers) 
      {  
          var theResults = new ArrayList(0);
          foreach(var possibleNumber in maybeNumbers) 
          {
              double myDouble;
              if (double.tryParse(possibleNumber, out myDouble))
                         theResults.Add(possibleNumber);// OR theResults.Add(myDouble); //depending on what you want
          }
          return theResults; 
      }
      

      【讨论】:

        【解决方案4】:
        • 摆脱死循环
        • 遍历您可能的数字
        • 用 try ... catch only isNumber 包围

        如果有异常不要增加数字的数量。 并且不要为此返回泛型,因为您真正需要返回的只是一个整数。

        你需要类似的东西(伪代码):

        numberOfNumbers = 0;
        
        while ( there is sth to handle )
        {
           take element to handle
           try
           {
              check it
              numberOfNumbers++;
           }
           catch ( )
           {
             // not a number
           }
           go to the next element
        }
        
        return numberOfNumbers
        

        当然假设 isNumber 在您的可能数字不是数字时会抛出一些异常。

        【讨论】:

          【解决方案5】:

          试试这个:

          static void Main(string[] args)
          {
              var maybe = new ArrayList(3);
              maybe.Add(100f);
              maybe.Add("not a number");
              maybe.Add(1000);
              foreach (var item in maybe)
              {
                  Console.WriteLine(item);
              }
              ArrayList res = new ArrayList(maybe.ToArray().Where((o) => o.IsNumber()).ToArray());
              foreach (var item in res)
              {
                  Console.WriteLine(item);
              }
          }
          
          public static bool IsNumber(this object item)
          {
              const TypeCode filter = TypeCode.Double | TypeCode.Int16 | TypeCode.Int32 | TypeCode.Int64
                  | TypeCode.Single | TypeCode.UInt16 | TypeCode.UInt32 | TypeCode.UInt64;
              Type t = item.GetType();
              if (t.IsPrimitive)
              {                
                  TypeCode code = System.Type.GetTypeCode(t);
                  return (code & filter) > 0;
              }
              return false;
          }
          

          【讨论】:

            猜你喜欢
            • 2013-06-11
            • 1970-01-01
            • 2012-08-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-12-25
            • 1970-01-01
            相关资源
            最近更新 更多