的可能範圍,我的ID(int
)像獲取INT收集
[1,2,3,5,7,8,11,13,14..]
列表是有一個快速/智能方式(LINQ?)來獲取所有的id,或者如果可能的話,範圍是多少? 結果應該像[1-3, 5, 7-8, 11, 13-14]
。
當然,很容易循環和計算int值來獲得結果,但我確定必須有一個更簡單的方法來做到這一點。
的可能範圍,我的ID(int
)像獲取INT收集
[1,2,3,5,7,8,11,13,14..]
列表是有一個快速/智能方式(LINQ?)來獲取所有的id,或者如果可能的話,範圍是多少? 結果應該像[1-3, 5, 7-8, 11, 13-14]
。
當然,很容易循環和計算int值來獲得結果,但我確定必須有一個更簡單的方法來做到這一點。
老學校的方式與一個單一的循環。
try
{
List<int> i = new List<int>() { 1, 2, 3, 5, 7, 8, 11, 13, 14 };
int istart = i[0];
bool flag = false;
// Use StringBuilder
for(int index = 0;index<i.Count-1;index++)
{
if ((i[index] + 1) == i[index + 1])
{
flag = true;
continue;
}
else
{
if (!flag)
Console.Write(istart);
else
Console.Write(istart + "-" + i[index]);
Console.Write(",");
flag = false;
istart = i[index + 1];
}
}
if (istart + 1 == i[i.Count - 1])
Console.Write(istart + "-" + i[i.Count - 1]);
else
Console.WriteLine(istart);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine();
Console.WriteLine("Done");
Console.Read();
輸入List<int> i = new List<int>() { 1, 2, 3, 5, 7, 8, 11, 13, 14 };
輸入List<int> i = new List<int>() { 1, 2, 3, 4, 5, 7, 8, 11, 13, 13 };
輸入List<int> i = new List<int>() { 1, 4, 5, 7, 8, 9, 2, 13, 15, 17 };
有一個LINQ的方式來做到這一點(如果號碼不重複),但我不知道這是否是簡單:
int last = -1;
int rank = 0;
IEnumerable<string> grouped = arr
.GroupBy(i =>
{
rank += i - last - 1;
last = i;
return rank;
})
.Select(g => g.Count() == 1 ? g.First().ToString()
: g.First().ToString() + "-" + g.Last().ToString());
似乎相當複雜對我來說,比需要更多的資源密集型並不靈活。 Linq對於很多案例來說都很棒,但有時候它並不適合。簡單的循環有時是最好的,你可以得到:
IEnumerable<string> Group(IEnumerable<int> sortedArr)
{
using (var en = sortedArr.GetEnumerator())
{
if (!en.MoveNext())
{
yield break;
}
int first = en.Current;
int last = first;
int count = 1;
while (true)
{
bool end;
if ((end = !en.MoveNext()) || en.Current - last > 1)
{
if (count == 1)
{
yield return first.ToString();
}
//else if (count == 2)
//{
// yield return first.ToString();
// yield return last.ToString();
//}
else
{
yield return first.ToString() + "-" + last.ToString();
}
if (end) { yield break; }
first = en.Current;
count = 1;
}
else
{
++count;
}
last = en.Current;
}
}
}
基準
讓我們衡量如何(中)高效LINQ實際上是這裏10M陣列上:
simple loop: 328MB, 1.2sec
my linq: 790MB, 2.7sec
Fredous linq: 1100MB, 7days (estimated)
的代碼:
int size = 10000000;
int[] arr = new int[size];
Random rnd = new Random(1);
arr[0] = 0;
for(int i = 1; i < size; ++i)
{
if (rnd.Next(100) < 25)
{
arr[i] = arr[i - 1] + 2;
}
else
{
arr[i] = arr[i - 1] + 1;
}
}
System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch();
st.Start();
var res = Group(arr).ToList();
st.Stop();
MessageBox.Show(st.ElapsedMilliseconds.ToString());
MessageBox.Show(res.Sum(s => s.Length).ToString());// to be sure the work is done
免責聲明這是大名單上的速度很慢,你應該做一個獨特的太
這應該做的伎倆
static void Main(string[] args)
{
//a list with a possible of duplicate
var theList = (new int[] { 1, 2, 3, 5, 7, 8, 11, 13, 14, 13 }).OrderBy(x => x).ToList();
var step1 = theList.Select((a, b) => theList.Skip(b).TakeWhile((x, y) => a == x || theList[b + y] - 1 == theList[b + y - 1]));
var step2 = step1.GroupBy(x => x.Last())
.Select(x => x.SelectMany(y => y).Distinct())
.Select(x => x.Count() > 1 ? string.Format("{0}-{1}", x.First(), x.Last()) : x.First().ToString());
var result = string.Format("[{0}]", string.Join(", ", step2));
}
考慮一個有序列表和唯一的ID,我認爲最簡單的方法是使用經典爲和而
List<int> ids = new List<int>() { 1, 2, 3, 5, 7, 8, 11, 13, 14 };
int i = 0;
bool isrange;
for(i=0;i<ids.Count;i++)
{
isrange = false;
Console.Write(ids[i]);
while (i < ids.Count-1 && ids[i + 1] == ids[i] + 1)
{
i++;
isrange = true;
}
if (isrange)
Console.Write("-" + ids[i]);
if (!(i + 1 == ids.Count))
Console.Write(",");
}
什麼是產生一系列的邏輯是什麼?爲什麼不是1-5,3-8等? – Sajeetharan
_is有一個快速/智能的方式(linq?)_ - 如果通過「快」你的意思是執行速度,那麼「foreach」將總是更快然後LINQ – Fabio