Linq to Objects - 从数字列表中返回数字对

发布于 2024-10-07 22:47:16 字数 273 浏览 7 评论 0原文

var nums = new[]{ 1, 2, 3, 4, 5, 6, 7};
var pairs  = /* some linq magic here*/ ;

=> pairs = { {1, 2}, {3, 4}, {5, 6}, {7, 0} }

pairs 的元素应该是二元素列表,或者是某些元素的实例具有两个字段的匿名类,类似于 new {First = 1, Second = 2}

var nums = new[]{ 1, 2, 3, 4, 5, 6, 7};
var pairs  = /* some linq magic here*/ ;

=>
pairs = { {1, 2}, {3, 4}, {5, 6}, {7, 0} }

The elements of pairs should be either two-element lists, or instances of some anonymous class with two fields, something like new {First = 1, Second = 2}.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

疏忽 2024-10-14 22:47:17

另一种选择是使用 SelectMany LINQ 方法。这更适合那些希望遍历项目列表并为每个项目返回 2 个或更多属性的人。无需为每个属性再次循环遍历列表,只需一次。

var list = new [] {//Some list of objects with multiple properties};

//Select as many properties from each Item as required. 
IEnumerable<string> flatList = list.SelectMany(i=> new[]{i.NameA,i.NameB,i.NameC});

Another option is to use the SelectMany LINQ method. This is more for those who wish to iterate through a list of items and for each item return 2 or more of it's properties. No need to loop through the list again for each property, just once.

var list = new [] {//Some list of objects with multiple properties};

//Select as many properties from each Item as required. 
IEnumerable<string> flatList = list.SelectMany(i=> new[]{i.NameA,i.NameB,i.NameC});
笑咖 2024-10-14 22:47:17

另一个使用 indexindex + 1 的简单解决方案。

var nums = Enumerable.Range(1, 10);
var pairs = nums.Select((item, index) =>
  new { First = item, Second = nums.ElementAtOrDefault(index + 1) })
    .SkipLastN(1);

pairs.ToList().ForEach(p => Console.WriteLine($"({p.First}, {p.Second}) "));

最后一项无效,必须使用 SkipLastN() 删除。

Another simple solution using index and index + 1.

var nums = Enumerable.Range(1, 10);
var pairs = nums.Select((item, index) =>
  new { First = item, Second = nums.ElementAtOrDefault(index + 1) })
    .SkipLastN(1);

pairs.ToList().ForEach(p => Console.WriteLine($"({p.First}, {p.Second}) "));

Last item is invalid and must be removed with SkipLastN().

抱猫软卧 2024-10-14 22:47:17

这给出了所有可能的对(vb.net):

Dim nums() = {1, 2, 3, 4, 5, 6, 7}
Dim pairs = From a In nums, b In nums Where a <> b Select a, b

编辑:

 Dim allpairs = From a In nums, b In nums Where b - a = 1 Select a, b
 Dim uniquePairs = From p In allpairs Where p.a Mod 2 <> 0 Select p

注意:最后一对丢失,正在处理

编辑:

uniquePairs 与对 {nums.Last,0}

this gives all possible pairs(vb.net):

Dim nums() = {1, 2, 3, 4, 5, 6, 7}
Dim pairs = From a In nums, b In nums Where a <> b Select a, b

Edit:

 Dim allpairs = From a In nums, b In nums Where b - a = 1 Select a, b
 Dim uniquePairs = From p In allpairs Where p.a Mod 2 <> 0 Select p

note: the last pair is missing, working on it

Edit:

union uniquePairs with the pair {nums.Last,0}

2024-10-14 22:47:16

默认的 linq 方法都无法通过一次扫描来延迟执行此操作。压缩序列本身会进行两次扫描,并且分组并不完全是懒惰的。最好的选择是直接实现它:

public static IEnumerable<T[]> Partition<T>(this IEnumerable<T> sequence, int partitionSize) {
    Contract.Requires(sequence != null)
    Contract.Requires(partitionSize > 0)

    var buffer = new T[partitionSize];
    var n = 0;
    foreach (var item in sequence) {
        buffer[n] = item;
        n += 1;
        if (n == partitionSize) {
            yield return buffer;
            buffer = new T[partitionSize];
            n = 0;
        }
    }
    //partial leftovers
    if (n > 0) yield return buffer;
}

None of the default linq methods can do this lazily and with a single scan. Zipping the sequence with itself does 2 scans and grouping is not entirely lazy. Your best bet is to implement it directly:

public static IEnumerable<T[]> Partition<T>(this IEnumerable<T> sequence, int partitionSize) {
    Contract.Requires(sequence != null)
    Contract.Requires(partitionSize > 0)

    var buffer = new T[partitionSize];
    var n = 0;
    foreach (var item in sequence) {
        buffer[n] = item;
        n += 1;
        if (n == partitionSize) {
            yield return buffer;
            buffer = new T[partitionSize];
            n = 0;
        }
    }
    //partial leftovers
    if (n > 0) yield return buffer;
}
走走停停 2024-10-14 22:47:16

试试这个:

int i = 0;
var pairs = 
  nums
    .Select(n=>{Index = i++, Number=n})
    .GroupBy(n=>n.Index/2)
    .Select(g=>{First:g.First().Number, Second:g.Last().Number});

Try this:

int i = 0;
var pairs = 
  nums
    .Select(n=>{Index = i++, Number=n})
    .GroupBy(n=>n.Index/2)
    .Select(g=>{First:g.First().Number, Second:g.Last().Number});
我不在是我 2024-10-14 22:47:16
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7 };
var result = numbers.Zip(numbers.Skip(1).Concat(new int[] { 0 }), (x, y) => new
        {
            First = x,
            Second = y
        }).Where((item, index) => index % 2 == 0);
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7 };
var result = numbers.Zip(numbers.Skip(1).Concat(new int[] { 0 }), (x, y) => new
        {
            First = x,
            Second = y
        }).Where((item, index) => index % 2 == 0);
酒中人 2024-10-14 22:47:16

(警告:看起来很丑)

var pairs = x.Where((i, val) => i % 2 == 1)
            .Zip(
            x.Where((i, val) => i % 2 == 0),
                (first, second) =>
                new
                {
                    First = first,
                    Second = second
                })
            .Concat(x.Count() % 2 == 1 ? new[]{
                new
                {
                    First = x.Last(),
                    Second = default(int)
                }} : null);

(warning: looks ugly)

var pairs = x.Where((i, val) => i % 2 == 1)
            .Zip(
            x.Where((i, val) => i % 2 == 0),
                (first, second) =>
                new
                {
                    First = first,
                    Second = second
                })
            .Concat(x.Count() % 2 == 1 ? new[]{
                new
                {
                    First = x.Last(),
                    Second = default(int)
                }} : null);
美羊羊 2024-10-14 22:47:16

这可能比您需要的更笼统 - 您可以设置自定义 itemsInGroup

int itemsInGroup = 2;
var pairs = nums.
            Select((n, i) => new { GroupNumber = i / itemsInGroup, Number = n }).
            GroupBy(n => n.GroupNumber).
            Select(g => g.Select(n => n.Number).ToList()).
            ToList();

编辑:

如果您想附加零(或其他数字),以防最后一个组的大小不同:

int itemsInGroup = 2;
int valueToAppend = 0;
int numberOfItemsToAppend = itemsInGroup - nums.Count() % itemsInGroup;

var pairs = nums.
            Concat(Enumerable.Repeat(valueToAppend, numExtraItems)).
            Select((n, i) => new { GroupNumber = i / itemsInGroup, Number = n }).
            GroupBy(n => n.GroupNumber).
            Select(g => g.Select(n => n.Number).ToList()).
            ToList();

This might be a bit more general than you require - you can set a custom itemsInGroup:

int itemsInGroup = 2;
var pairs = nums.
            Select((n, i) => new { GroupNumber = i / itemsInGroup, Number = n }).
            GroupBy(n => n.GroupNumber).
            Select(g => g.Select(n => n.Number).ToList()).
            ToList();

EDIT:

If you want to append zeros (or some other number) in case the last group is of a different size:

int itemsInGroup = 2;
int valueToAppend = 0;
int numberOfItemsToAppend = itemsInGroup - nums.Count() % itemsInGroup;

var pairs = nums.
            Concat(Enumerable.Repeat(valueToAppend, numExtraItems)).
            Select((n, i) => new { GroupNumber = i / itemsInGroup, Number = n }).
            GroupBy(n => n.GroupNumber).
            Select(g => g.Select(n => n.Number).ToList()).
            ToList();
国粹 2024-10-14 22:47:16
public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max)
{
    return InSetsOf(source, max, false, default(T));
}

public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max, bool fill, T fillValue)
{
    var toReturn = new List<T>(max);
    foreach (var item in source)
    {
        toReturn.Add(item);
        if (toReturn.Count == max)
        {
            yield return toReturn;
            toReturn = new List<T>(max);
        }
    }
    if (toReturn.Any())
    {
        if (fill)
        {
            toReturn.AddRange(Enumerable.Repeat(fillValue, max-toReturn.Count));
        }
        yield return toReturn;
    }
}

用法:

var pairs = nums.InSetsOf(2, true, 0).ToArray();
public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max)
{
    return InSetsOf(source, max, false, default(T));
}

public static IEnumerable<List<T>> InSetsOf<T>(this IEnumerable<T> source, int max, bool fill, T fillValue)
{
    var toReturn = new List<T>(max);
    foreach (var item in source)
    {
        toReturn.Add(item);
        if (toReturn.Count == max)
        {
            yield return toReturn;
            toReturn = new List<T>(max);
        }
    }
    if (toReturn.Any())
    {
        if (fill)
        {
            toReturn.AddRange(Enumerable.Repeat(fillValue, max-toReturn.Count));
        }
        yield return toReturn;
    }
}

usage:

var pairs = nums.InSetsOf(2, true, 0).ToArray();
Bonjour°[大白 2024-10-14 22:47:16
IList<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7};
var grouped = numbers.GroupBy(num =>
{
   if (numbers.IndexOf(num) % 2 == 0)
   {
      return numbers.IndexOf(num) + 1;
   }
   return numbers.IndexOf(num);
});

如果您需要最后一对填充零,则如果列表计数为奇数,则可以在进行分组之前添加它。

if (numbers.Count() % 2 == 1)
{
   numbers.Add(0);
}

另一种方法可能是:

var groupedIt = numbers
   .Zip(numbers.Skip(1).Concat(new[]{0}), Tuple.Create)
   .Where((x,i) => i % 2 == 0);

或者您使用 MoreLinq,它有很多有用的扩展:

IList<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7};
var batched = numbers.Batch(2);
IList<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7};
var grouped = numbers.GroupBy(num =>
{
   if (numbers.IndexOf(num) % 2 == 0)
   {
      return numbers.IndexOf(num) + 1;
   }
   return numbers.IndexOf(num);
});

If you need the last pair filled with zero you could just add it before doing the grouping if the listcount is odd.

if (numbers.Count() % 2 == 1)
{
   numbers.Add(0);
}

Another approach could be:

var groupedIt = numbers
   .Zip(numbers.Skip(1).Concat(new[]{0}), Tuple.Create)
   .Where((x,i) => i % 2 == 0);

Or you use MoreLinq that has a lot of useful extensions:

IList<int> numbers = new List<int> {1, 2, 3, 4, 5, 6, 7};
var batched = numbers.Batch(2);
蔚蓝源自深海 2024-10-14 22:47:16
    var w =
        from ei in nums.Select((e, i) => new { e, i })
        group ei.e by ei.i / 2 into g
        select new { f = g.First(), s = g.Skip(1).FirstOrDefault() };
    var w =
        from ei in nums.Select((e, i) => new { e, i })
        group ei.e by ei.i / 2 into g
        select new { f = g.First(), s = g.Skip(1).FirstOrDefault() };
顾挽 2024-10-14 22:47:16
 var nums = new float[] { 1, 2, 3, 4, 5, 6, 7 };
 var enumerable = 
        Enumerable
          .Range(0, nums.Length)
          .Where(i => i % 2 == 0)
          .Select(i => 
             new { F = nums[i], S = i == nums.Length - 1 ? 0 : nums[i + 1] });
 var nums = new float[] { 1, 2, 3, 4, 5, 6, 7 };
 var enumerable = 
        Enumerable
          .Range(0, nums.Length)
          .Where(i => i % 2 == 0)
          .Select(i => 
             new { F = nums[i], S = i == nums.Length - 1 ? 0 : nums[i + 1] });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文