提高循环效率

时间:2015-07-19 13:39:43

标签: c# loops if-statement foreach iteration

背景

我有一张包含数字列表的表格。我检索此列表并将其放入数据表中。然后我遍历表格中的行,并显示表格中没有的1000到9999之间的每个数字。

My Loop

static DataTable table = new DataTable();

foreach (DataRow row in table.Rows)
            {
                int id = Convert.ToInt32(row["stationid"]);

                for (int i = 1000; i < 9999 - table.Rows.Count; i = i++)
                {
                    if (i != id)
                    {

                                stationIdsTb.Text += Environment.NewLine;
                                stationIdsTb.Text += i.ToString();

                     }
                 }
             }

问题

但是这种方法确实有效。这非常慢。

是否有更有效,更快捷的方法来计算1000到9999之间不在数据表中的数字?

5 个答案:

答案 0 :(得分:3)

你的循环并不慢。但所有这些字符串连接都是。由于字符串是不可变的,因此每次连接都会创建一个新的library(shiny) ## test dataframe df <- data.frame(id = c("1","1","1","1","1","1","2","2","2","2"), brand = c("w","w","w","s","s","s","w","w","w","s"), model = c("w123","w123","w456","s99","s88","s88","w123","w456","w456","s99"), amount = c(10,9,7,8,6,4,7,3,2,8)) df$id=as.character(df$id) df$brand=as.character(df$brand) df$model=as.character(df$model) shinyServer(function(input, output) { output$table <- renderDataTable({ if(input$brand!="all") {df=df[which(df$brand==input$brand),]} if(input$model!="all") {df=df[which(df$model==input$model),]} df }) }) 对象,这会不必要地复制内存并增加很多GC压力。

使用string

StringBuilder

另一方面,写var sb = new StringBuilder(); foreach (DataRow row in table.Rows) { int id = Convert.ToInt32(row["stationid"]); var max = Math.Max(9999, table.Rows.Count); for (int i = 1000; i < max; ++i) { if (i != id) sb.AppendLine().Append(i); // Or just sb.AppendLine(i); maybe? } } stationIdsTb.Text = sb.ToString(); 确实错误,因为它基本上是无操作。

更新

  

显示表格中没有的1000到9999之间的每个数字。

这不正是你的代码正在做什么,但如果它真的是你想要的,这里有一个更简单的方法:

i = i++

答案 1 :(得分:2)

而不是使用var stationIds = new HashSet<int>( table.Rows.Cast<DataRow>().Select(row => Convert.ToInt32(row["stationid"])) ); var sb = new StringBuilder(); for (var i = 1000; i <= 9999; ++i) { if (!stationIds.Contains(i)) sb.AppendLine(i); } stationIdsTb.Text = sb.ToString(); 使用stationIdsTb.Text += ...

StringBuilder

答案 2 :(得分:2)

如果您愿意在表格中显示1000到9999之间的数字,那么您做错了。您可以将&#34; stationid&#34; 列设置为主键,并在for循环内部查看主键是否包含当前编号。如果我弄错了,请纠正我,但这应该是正确的解决方案:

table.PrimaryKey = new DataColumn[] { table.Columns["stationid"] };

StringBuilder sb = new StringBuilder();
for (int i = 1000; i <= 9999; i++)
{
    if (!table.Rows.Contains(i))
        sb.AppendLine(i);
}

stationIdsTb.Text = sb.ToString();

设置主键后,您也可以这样做:

stationIdsTb.Text = String.Join(Environment.NewLine, Enumerable.Range(1000, 9000).Where(number => !table.Rows.Contains(number)));

答案 3 :(得分:0)

很多问题 1)如果你想要在前端使用linq 2)不要使用数据表。无论需要什么列,只需选择那些以使数据表大小更小。

答案 4 :(得分:0)

以下是我会怎么做...除非我错过了什么,不要理解当前的方法 - 让我们说1000不在表中 - 你最终会检查1,000并将其添加到表中每行的结果中。我假设您需要一个明确的缺失数字列表。

// get all the numbers in the list
HashSet<int> numbersInTable = new HashSet<int>(dataTable.AsEnumerable().Select(a => (int)a["StationId"]));

// between 1000-9999, find numbers not in the set
List<int> missingNumbers = Enumerable.Range(1000, 9000).Except(numbersInTable).ToList();

// convert to a string
string result = String.Join(Environment.NewLine, missingNumbers.ConvertAll<string>(a => a.ToString()));