如何编写通过在序列中丢失项目来生成ID的函数?
如何编写一个算法,可以将未使用的ID从格式为“C00”的1到99开始的序列中取出?例如NewId(['C01', 'C02', 'C03'])
应该发出'C04',但NewId(['C02', 'C03', 'C04'])
应该发出C01,而NewId(['C01', 'C03', 'C04'])
应该产生C02。如何编写通过在序列中丢失项目来生成ID的函数?
我写了一个实现,但结果是错误的。
示例:CAT_ID:C01,C02,C05,C06,C11。当我运行它时,预期的结果是C03。我的算法如下:
- 排序ID ASC
- 遍历每个项目在列表中
- 比较第一值与未来,如果他们是不一样的,加1并退出循环。
这是我的代码:
public static string Get_AreaID_Auto()
{
string result = "";
if (db.TESTs.ToList().Count <= 0)
{
result = "01";
}
else
{
int maxId = 0;
foreach (var item in db.TESTs.OrderBy(e => e.CAT_ID).ToList())
{
if (int.Parse(item.CAT_ID.Substring(1)) + 1 != int.Parse(item.CAT_ID.Substring(1)))
{
maxId = int.Parse(item.CAT_ID.Substring(1) + 1);
break;
}
}
switch (maxId.ToString().Length)
{
case 1:
if (maxId == 9)
{
result = "10";
}
else
result = "0" + (maxId + 1);
break;
case 2:
result = "" + (maxId + 1);
break;
default:
break;
}
}
return "C" + result;
}
有人能说出什么是错的?
这应该为你工作:
public static string Get_AreaID_Auto()
{
var existing = db.TESTs.Select(e => e.CAT_ID).OrderBy(x => x).ToList();
if (existing.Count == 0)
{
return "C01";
}
else
{
return
existing
.Concat(new [] { "" })
.Select((x, n) => new
{
actual = x,
expected = String.Format("C{0:00}", n + 1),
})
.Where(x => x.actual != x.expected)
.Select(x => x.expected)
.First();
}
}
这使用生成和测试方法。不需要解析。
我刚刚实现了.Concat(new [] { "" })
的更改,现在不再需要if
语句。你可以这样做,而不是:
public static string Get_AreaID_Auto()
{
return
db.TESTs
.Select(e => e.CAT_ID)
.OrderBy(x => x)
.ToArray()
.Concat(new [] { "" })
.Select((x, n) => new
{
actual = x,
expected = String.Format("C{0:00}", n + 1),
})
.Where(x => x.actual != x.expected)
.Select(x => x.expected)
.First();
}
好吧,你是对的,它的工作,没有解析。当我使用GeirGrusom代码时,我想念LINQ to Entities无法识别方法'Int32 Parse(System.String)'方法,并且这种方法不能被转换成商店表达式' –
嗨enigmativity,在这里,你忘记了'09',接下来是'10',它错误'Sequence contains no elements', –
@BrianCrist - 我修正了它。问题是两个序列完全相同时失败了。我用'.Concat(new [] {“”})'修复了这个问题。 – Enigmativity
这里是一个解决方案,我想会的工作:
var items = db.TESTs.Select(x => int.Parse(x.CAT_ID.Substring(1))).OrderBy(v => v).ToArray();
if(!items.Any())
return "C01";
int current = 0;
for (int i = 0; i < items.Length; i++)
{
if (items[i] > current + 1)
return "C" + (current + 1) .ToString("00");
current = items[i];
}
return "C" + (items.Max() + 1).ToString("00");
没问题,请仔细阅读问题,然后给我一些建议code.thank家伙 –
改变到应该希望工作的东西。 – GeirGrusom
尝试3个案例:'1,2,3,5,6 => 4; 2,3,4,5,6 => 1; 1,2,3,4,5 => 6'。不工作 –
试试这个
public static string Get_AreaID_Auto()
{
string result = "";
if (db.TESTs.ToList().Count <= 0)
{
result = "01";
}
else
{
var item = db.TESTs.OrderByDescending(e => e.CAT_ID).First();
result = int.Parse(item.CAT_ID.Substring(1)) + 1;
}
return string.Format("C{0:D3}",result);
}
更新的代码......现在试试这个
public static string Get_AreaID_Auto()
{
string result = "";
if (db.TESTs.ToList().Count <= 0)
{
result = "01";
}
else
{
var items = db.TESTs.OrderBy(e => e.CAT_ID).ToArray();
for(int i=0;i<items.count;i++)
{
if ((i==items.count-1) || (int.Parse(items[i].CAT_ID.Substring(1)) + 1 != int.Parse(items[i+1].CAT_ID.Substring(1))))
{
result = int.Parse(items[i].CAT_ID.Substring(1) + 1);
break;
}
}
}
return string.Format("C{0:D2}",result);
}
那么,更好的方法是使用数据库自动增量功能,但假设你正在尝试在代码中这样做的原因。 – Viru
这是不行的。在这里,我不想使用数据库的身份自动增量,它不合逻辑。 –
为什么不使用的数据库'自动Increment'功能并保存自己的数据库中大量的心脏疼 – 3dd
自动递增的不是逻辑。例如:你有1,2,3,4,5。如果你删除2,3,那么Id将会是6,而不是逻辑。 –
你是什么意思不是逻辑,如果那些被删除,你想要新的id是2 2,3如果删除 – 3dd