我一直在尝试在类型为int的List中找到(并替换)相邻的相似(等值)元素。
在实施程序时,我只记得一个约束: - 也就是说,查找/替换彼此相邻的元素的长度为=(或>)3。
这就是我所做的:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var list = new[] {2, 2, 2, 3, 3, 4, 4, 4, 4};
for (var i = 2; i < list.Length; i++)
{
if (list[i] == list[i - 1] && list[i] == list[i - 2])
{
list[i] = 0;
list[i - 1] = 0;
list[i - 2] = 0;
}
}
foreach(int item in list)
{
Console.Write(item);
}
Console.ReadKey();
}
}
我将所有相邻的相似/相等值替换为0.但是有一个问题: 如果重复值长度为3/6/9,代码运行正常,依此类推,如果重复数字的长度不是3/6/9等,它不会将数字值更改为0
如果您运行该程序,您将看到以下输出:000330004(因为有3个2的数量因此它工作正常,但因为有4个4的数量所以它忽略了最后一位数字并没有将其转换为0)。
我需要什么:我理解发生了什么,以及为什么会发生这种情况。我似乎无法拥有它,因为我希望它能够工作。如果有人能告诉我怎么做,我会很感激。感谢。
答案 0 :(得分:1)
最后一个没有被转换,因为3 4的在它首先被转换为0之前。
第7次迭代:
{00033**444**4}
第8次迭代:
{00033**000**4}
第9次迭代:
{000330004} //the 9th iteration loops over the 8th one.
您应该做的是找到任何重复数字的开头和结尾,然后修改它们的值。您当前的方法替换了3个类似的值,一次3个。
答案 1 :(得分:1)
当你找到3个重复元素时,不要替换它们 - 计算它们。保持最后一个值和元素数(在当前值之前)等于此值。当值更改为其他值时 - 如果该数字为>=3
,则替换计数的元素数。
int previous = list[0];
int count = 1;
int i;
for (i = 1; i < list.Length; i++)
{
if (list[i] == previous)
{
count++;
}
else
{
if (count >= 3)
{
for (int j = 1; j <= count; j++)
list[i-j] = 0;
}
count = 1;
previous = list[i];
}
}
// repeat the else logic from the loop above:
if (count >= 3)
{
for (int j = 1; j <= count; j++)
list[i-j] = 0;
}
从概念上讲,您接受的问题是Count similar adjacent items in List<string>
的答案答案 2 :(得分:1)
这适用于任意数量的整数:
namespace Test
{
using System;
using System.Collections.Generic;
class MainClass
{
public static void Main (string[] args)
{
List<int> data = new List<int> ();
data.AddRange (new int[] { 2, 2, 2, 3, 3, 4, 4, 4, 4 });
int instance_counter = 0;
int previous_end = 0;
for (int i = 0; i < data.Count - 1; i++) {
instance_counter++;
if (data [i] != data [i + 1]) {
if (instance_counter > 2) {
for (int j = previous_end; j < i + 1; j++) {
data [j] = 0;
}
previous_end = i + 1;
}
instance_counter = 0;
previous_end = i + 1;
}
}
if (instance_counter > 2) {
for (int j = previous_end; j < data.Count; j++) {
data [j] = 0;
}
}
foreach (int x in data) {
Console.WriteLine (x);
}
}
}
}
答案 3 :(得分:1)
使用LINQ的另一个解决方案。
List<int> data = new List<int>();
data.AddRange(new int[] { 2, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5 });
var consecutiveIndexes = data.Select((value, index) => new { Index = index, Value = value })
.OrderBy(container => container.Index)
.GroupBy(container => container.Value, group => group.Index)
// Get consecutive indexes where count > 2 and elements are consecutive
.Where(group => group.Count() > 2 &&
//return next index if previous index is one less than the next index else -1
group.Aggregate((prevIndex, nextIndex) => prevIndex + 1 == nextIndex ? nextIndex : -1) > -1)
.SelectMany(index => index);
var filteredData = data.Select((x, i) => consecutiveIndexes.Contains(i) ? 0 : x);
答案 4 :(得分:0)
我意识到你已经有了答案,但我无法入睡,看到你的问题让我有意思去做。我原本想使用Enumerable.Aggregate
,但无法以漂亮的方式进行,但仍想尝试以不同的方式解决问题。
我已经使用一些随机列表(包括空列表,当然还有您的列表)测试了它,它适用于我能想到的所有情况。
编辑:我再次看了你的代码并提出了一个更简单但更无聊的答案(只对你所做的做了很小的改动)所以发布了(方法2)完整性。
方法1:&#39; fun&#39;方式强>
using System;
using System.Collections.Generic;
using System.Linq;
public class Test
{
public static void Main()
{
var list = new[] {2, 2, 2, 3, 3, 4, 4, 4, 4};
// tuples is a list of Tuple<current value, number of repetitions of value>
var tuples = new List<Tuple<int, int>>();
var currentTuple = Tuple.Create(0, 0);
foreach ( var value in list )
{
bool newValue = value != currentTuple.Item1;
if ( newValue && currentTuple.Item2 != 0 )
tuples.Add(currentTuple);
currentTuple = Tuple.Create(
value,
newValue ? 1 : currentTuple.Item2 + 1);
}
tuples.Add(currentTuple);
var result = new List<int>();
foreach ( var tuple in tuples )
result.AddRange(Enumerable.Repeat(tuple.Item2 > 2 ? 0 : tuple.Item1, tuple.Item2));
foreach ( var item in result )
Console.WriteLine(item);
}
}
方法2:无聊的方式
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var list = new[] {2, 2, 2, 3, 3, 4, 4, 4, 4};
var copy = list.ToArray();
for (var i = 2; i < list.Length; i++)
{
if (list[i] == list[i - 1] && list[i] == list[i - 2])
{
copy[i] = 0;
copy[i - 1] = 0;
copy[i - 2] = 0;
}
}
foreach ( int item in copy )
Console.Write(item);
}
}