Index out of bounds when comparing two lists - c#

I searched all over the internet to find an answer for this. I am looping through two lists (list1 and list2) with nested for loops and removing duplicate records in first list based on three criteria. If all records in these two lists match each other, I get an out of bounds error. I assume it happens when I remove all the items from the first list, and when it finally reduces to 0, and does not have any records to loop through, but putting an if statement to check the count of the first list (if inbox_emails_filtered_contacts.Count > 0) does not help either. Please let me know if any of you can tell me why this errors out.
Outlook Add-in in C#.net
for (int i = 0; i < list1.Count; i++)
{
for (int j = 0; j < list2.Count; j++)
{
if (list1.Count > 0)
{
if ((list1[i].username == registered_user)
&& (list1[i].from_email.ToLower() == list2[j].from_email.ToLower())
&& (list1[i].email_subject == list2[j].email_subject)
&& (list1[i].email_timestamp.ToLongDateString() == list2[j].email_timestamp.ToLongDateString()))
{
//Remove the duplicate email from inbox_emails_filtered_contacts
list1.RemoveAt(i);
}
}
}
}

I would suggest using while loop here. Also you need to break out of inner loop if a match is found to restart checking from the beginning.
int i = 0;
while (i < list1.Count)
{
int found = 0;
for (int j = 0; j < list2.Count; j++)
{
if ((list1[i].username == registered_user)
&& (list1[i].from_email.ToLower() == list2[j].from_email.ToLower())
&& (list1[i].email_subject == list2[j].email_subject)
&& (list1[i].email_timestamp.ToLongDateString() == list2[j].email_timestamp.ToLongDateString()))
{
//Remove the duplicate email from inbox_emails_filtered_contacts
list1.RemoveAt(i);
found = 1;
break;
}
}
if (!found)
{
i++;
}
}

here is an implementation of an Email class
class Email:IComparable<Email>
{
private static int _Id;
public Email()
{
Id = _Id++;
}
public int Id { get; private set; }
public string UserName { get; set; }
public string Body { get; set; }
public string Subject { get; set; }
public DateTime TimeStamp { get; set; }
public override int GetHashCode()
{
return UserName.GetHashCode() ^ Body.GetHashCode() ^ Subject.GetHashCode();
}
public int CompareTo(Email other)
{
return GetHashCode().CompareTo(other.GetHashCode());
}
public override string ToString()
{
return String.Format("ID:{0} - {1}", Id, Subject);
}
public override bool Equals(object obj)
{
if (obj is Email)
return CompareTo(obj as Email) == 0;
return false;
}
}
and 2 ways of getting the diff.
var list1 = new List<Email>();
var ran = new Random();
for (int i = 0; i < 50; i++)
{
list1.Add(new Email() { Body = "Body " + i, Subject = "Subject " + i, UserName = "username " + i, TimeStamp = DateTime.UtcNow.AddMinutes(ran.Next(-360, 60)) });
}
var list2 = new List<Email>();
for (int i = 0; i < 50; i++)
{
if (i % 2 == 0)
list2.Add(new Email() { Body = "Body " + i, Subject = "Subject Modifed" + i, UserName = "username " + i, TimeStamp = DateTime.UtcNow.AddMinutes(ran.Next(-360, 60)) });
else
list2.Add(new Email() { Body = "Body " + i, Subject = "Subject " + i, UserName = "username " + i, TimeStamp = DateTime.UtcNow.AddMinutes(ran.Next(-360, 60)) });
}
foreach (var item in list2.Intersect<Email>(list1))
{
Console.WriteLine(item);
}
foreach (var item in list1)
{
for (int i = 0; i < list2.Count; i++)
{
if (list2[i].Equals(item))
{
Console.WriteLine(item);
list2.RemoveAt(i);
break;
}
}
}
Console.WriteLine(list2.Count);

Use a reverse for when you iterate a list/array while removing item out of it (snippet "forr" in Visual) :
for (int i = list1.Count - 1; i >= 0; i--)

The likelyhood is that there are multiple duplicates in application_emails and so removeAt(i) is being called multiple times. Your if will never catch the case where i is the last item in a list longer than 2 and you end up removing multiple times.
Additionally you will also end up skipping emails with the remove statement. Assume i=4, if you remove at 4 index 4 will contain a new item and i will be 5 on the next iteration. You may be better off with a while loop
int i=0;
while (i < inbox_emails.Count) {
bool foundDuplicate=false;
for (int j=0;j<for (int j = 0; j < application_emails.Count; j++) {
if ((inbox_emails[i].username == registered_user)
&& (inbox_emails[i].from_email.ToLower() == application_emails[j].from_email.ToLower())
&& (inbox_emails[i].email_subject == application_emails[j].email_subject)
&& (inbox_emails[i].email_timestamp.ToLongDateString() == application[j].email_timestamp.ToLongDateString()))
{
foundDuplicate=true;
break; // This is optional but it stops the j loop from continuing as we've found a duplicate
}
}
if (foundDuplicate) {
inbox_emails.RemoveAt(i);
} else {
i++;
}
}
If this is a single thread you could just replace the list using Linq, make sure you have a using System.Linq
inbox_emails = inbox_emails.Where(i=>
i.username != registered_user
|| ! application_emails.Any(j=>
i.from_email.ToLower() == j.from_email.ToLower()
&& i.email_subject == j.email_subject
&& i.email_timestamp.ToLongDateString() == j.email_timestamp.ToLongDateString()
)
).ToList();

Related

Determine whether each character in the first string can be uniquely replaced by a character in the second string so that the two strings are equal

Give two strings of equal size. Determine whether each character in the first string can be uniquely replaced by a character in the second string so that the two strings are equal. Display also the corresponding character pairs between the two strings. The code works well now.
Example 1:
For input data:
aab
ttd
The console will display:
True
a => t
b => d
Example 2:
For input data:
tab
ttd
The console will display:
False
In the second example the answer is false because there is no unique correspondence for the character 'a': both 't' and 'd' correspond to it.
This is my code:
using System;
namespace problemeJM
{
class Program
{
static void Main(string[] args)
{
string firstPhrase = Convert.ToString(Console.ReadLine());
string secondPhrase = Convert.ToString(Console.ReadLine());
string aux1 = string.Empty, aux2 = string.Empty;
bool x = true;
for (int i = 0; i < firstPhrase.Length; i++)
{
if (!aux1.Contains(firstPhrase[i]))
{
aux1 += firstPhrase[i];
}
}
for (int i = 0; i < secondPhrase.Length; i++)
{
if (!aux2.Contains(secondPhrase[i]))
{
aux2 += secondPhrase[i];
}
}
if (aux1.Length != aux2.Length)
{
Console.WriteLine("False");
}
else
{
for (int i = 0; i < firstPhrase.Length - 2; i++)
{
for (int j = 1; j < secondPhrase.Length - 1; j++)
{
if (firstPhrase[i] == firstPhrase[j] && secondPhrase[i] == secondPhrase[j])
{
x = true;
}
else if (firstPhrase[i] != firstPhrase[j] && secondPhrase[i] != secondPhrase[j])
{
x = true;
}
else if (firstPhrase[i] == firstPhrase[j] && secondPhrase[i] != secondPhrase[j])
{
x = false;
break;
}
else if (firstPhrase[i] != firstPhrase[j] && secondPhrase[i] == secondPhrase[j])
{
x = false;
break;
}
}
}
Console.WriteLine(x);
aux1 = string.Empty;
aux2 = string.Empty;
if (x == true)
{
for (int i = 0; i < firstPhrase.Length; i++)
{
if (!aux1.Contains(firstPhrase[i]))
{
aux1 += firstPhrase[i];
}
}
for (int i = 0; i < secondPhrase.Length; i++)
{
if (!aux2.Contains(secondPhrase[i]))
{
aux2 += secondPhrase[i];
}
}
for (int i = 0; i <= aux1.Length - 1; i++)
{
for (int j = 1; j <= aux2.Length; j++)
{
if (aux1[i] == aux1[j] && aux2[i] == aux2[j])
{
Console.WriteLine(aux1[i] + " => " + aux2[i]);
break;
}
else if (aux1[i] != aux1[j] && aux2[i] != aux2[j])
{
Console.WriteLine(aux1[i] + " => " + aux2[i]);
break;
}
}
}
}
}
}
}
}
I think you should use a Dictionary<char, char> as commented. But you need to check if there's a unique mapping in both string, so from s1 to s2 and from s2 to s1:
static bool UniqueMapping(string s1, string s2)
{
int length = Math.Min(s1.Length, s2.Length);
var dict = new Dictionary<char, char>(length);
for (int i = 0; i < length; i++)
{
char c1 = s1[i];
char c2 = s2[i];
bool contained = dict.TryGetValue(c1, out char c);
if (contained && c2 != c)
{
return false;
}
dict[c1] = c2;
}
return true;
}
Here are your samples. Note that i use UniqueMapping twice(if true after 1st):
static void Main(string[] args)
{
var items = new List<string[]> { new[]{ "aab", "ttd" }, new[] { "tab", "ttd" }, new[] { "ala bala portocala", "cuc dcuc efghficuc" }, new[] { "ala bala portocala", "cuc dcuc efghijcuc" } };
foreach (string[] item in items)
{
bool result = UniqueMapping(item[0], item[1]);
if(result) result = UniqueMapping(item[1], item[0]);
Console.WriteLine($"Word 1 <{item[0]}> Word 2 <{item[1]}> UniqueMapping? {result}");
}
}
.NET Fiddle: https://dotnetfiddle.net/4DtIyH

Cleaner Algorithm for List of Possibly Intersecting Ranges With Properties

I have these objects with a range and list of properties. My goal is to take a list of these objects and create a new list where no ranges overlap. When two ranges are overlapping the overlapping region can be replaced with an object with the union of the properties. I'm hoping a picture can explain this a little better than words can.
Untangling Of Ranges
I was able to achieve this with the following code however it is rather clunky and uses a goto which I try to avoid. The methodology behind this code is to compare every pair of ranges and if there is an intersection, replace both RangeObjects with up to three RangeObjects:
One for the part of rangeObject1 that doesn't intersect rangeObject2
One for the part of rangeObject2 that doesn't intersect rangeObject1
One for the intersection of rangeObject1 and rangeObject2 with unioned properties.
class RangeObject
{
RangeObject(int start, int end, List<object> properties)
{
Start = start;
End = end;
Properties = properties;
}
public int Start { get; set; }
public int End { get; set; }
public int Length { get => End - Start; }
public List<object> Properties { get; }
public bool IsInRange(int value)
{
return value > Start && value < End;
}
private List<RangeObject> UntangleRangeList(List<RangeObject> list)
{
List<RangeObject> list1 = new List<RangeObject>(list);
list1.Sort();
int start = 0;
startover:
for (int i = start; i < list1.Count; i++)
{
for (int j = i + 1; j < list1.Count; j++)
{
if (list1[i].Start < list1[j].End && list1[j].Start < list1[i].End)
{
list1.AddRange(UntangleRanges(list1[i], list1[j]));
list1.Remove(list1[j]);
list1.Remove(list1[i]);
goto startover;
}
}
start++;
}
list1.Sort();
return list1;
}
public List<RangeObject> UntangleRanges(RangeObject rangeObject1, RangeObject rangeObject2)
{
List<RangeObject> result = new List<RangeObject>();
//This is to reduce the number of if cases by allowing the asumption that rangeObject1 is first
if (rangeObject1.Start > rangeObject2.Start || ((rangeObject1.Start == rangeObject2.Start) && (rangeObject1.Length > rangeObject2.Length)))
{
RangeObject temp = rangeObject1;
rangeObject1 = rangeObject2;
rangeObject2 = temp;
}
if (rangeObject1.Start == rangeObject2.Start && rangeObject1.End == rangeObject2.End) //Ranges Equal
{
result.Add(new RangeObject(rangeObject1.Start, rangeObject1.End, rangeObject1.Properties.Union(rangeObject2.Properties).ToList()));//Return a RangeObject of Unioned Properties
}
else if(rangeObject1.IsInRange(rangeObject2.Start) && rangeObject1.IsInRange(rangeObject2.End))//Range2 contained in Range1
{
if (rangeObject1.Start != rangeObject2.Start)
{
result.Add(new RangeObject(rangeObject1.Start, rangeObject2.Start - rangeObject1.Start, rangeObject1.Properties));
}
result.Add(new RangeObject(rangeObject2.Start, rangeObject2.Length, rangeObject1.Properties.Union(rangeObject2.Properties).ToList()));
if (rangeObject1.End != rangeObject2.End)
{
result.Add(new RangeObject(rangeObject2.End, rangeObject1.End - rangeObject2.End, rangeObject1.Properties));
}
}
else if (rangeObject1.IsInRange(rangeObject2.Start))//Range2.Start contained in Range1
{
result.Add(new RangeObject(rangeObject1.Start, rangeObject2.Start - rangeObject1.Start, rangeObject1.Properties));
result.Add(new RangeObject(rangeObject2.Start, rangeObject1.End - rangeObject2.Start, rangeObject1.Properties.Union(rangeObject2.Properties).ToList()));
result.Add(new RangeObject(rangeObject1.End, rangeObject2.End - rangeObject1.End, rangeObject2.Properties));
}
else //No intersection, shouldn't happen
{
result.Add(rangeObject1);
result.Add(rangeObject2);
}
return result;
}
}
Any ideas on how to achieve this a little more elegantly? Or at least avoid the startover because when I cut up the ranges I end up relocating them to the end and changing the length/order of the list so it's hard to tell what ranges I've compared.
For the sake of simplicity I first get a big enough range to include all other ranges, but with an empty Properties field. This is achieved by getting the minimum and maximum value of all ranges.
Then I combine the ranges one after the other with a so-called untangled range list which at the beginning consists of only initialRange. During this process, untangledRanges remains sorted and without any overlapping ranges. So in the end, all the ranges are combined into a list of untangled ranges.
Based on your current code, this is all you need:
class RangeObject
{
public RangeObject(int start, int end, List<object> properties)
{
if (start >= end)
throw new Exception("'start' must be less than 'end'");
Start = start;
End = end;
Properties = properties;
}
public int Start { get; set; }
public int End { get; set; }
public int Length { get => End - Start; }
public List<object> Properties { get; set; }
public List<RangeObject> SplitAt(int point)
{
if (point <= this.Start || point >= this.End)
return new List<RangeObject> { this };
var result = new List<RangeObject>();
result.Add(new RangeObject(this.Start, point, this.Properties));
result.Add(new RangeObject(point, this.End, this.Properties));
return result;
}
public static List<RangeObject> UntangleRangeList(List<RangeObject> list)
{
var initialRange = GetInitialRange(list);
var untangledRanges = new List<RangeObject> { initialRange };
foreach (var rangeObject in list)
{
ExpandUntangleRanges(untangledRanges, rangeObject);
}
return untangledRanges;
}
private static void ExpandUntangleRanges(
List<RangeObject> alreadyUntangledRanges, RangeObject newRange)
{
int firstRangeIndex = alreadyUntangledRanges
.FindIndex(x => x.Start <= newRange.Start && newRange.Start < x.End);
int lastRangeIndex = alreadyUntangledRanges
.FindIndex(x => x.Start < newRange.End && newRange.End <= x.End);
var firstRange = alreadyUntangledRanges[firstRangeIndex];
if (firstRange.Start < newRange.Start)
{
// split the first range
alreadyUntangledRanges.RemoveAt(firstRangeIndex);
alreadyUntangledRanges.InsertRange(
firstRangeIndex, firstRange.SplitAt(newRange.Start));
firstRangeIndex++;
lastRangeIndex++;
}
var lastRange = alreadyUntangledRanges[lastRangeIndex];
if (newRange.End < lastRange.End)
{
// split the last range
alreadyUntangledRanges.RemoveAt(lastRangeIndex);
alreadyUntangledRanges.InsertRange(
lastRangeIndex, lastRange.SplitAt(newRange.End));
}
for (int i = firstRangeIndex; i <= lastRangeIndex; i++)
{
alreadyUntangledRanges[i].Properties = alreadyUntangledRanges[i]
.Properties.Union(newRange.Properties).ToList();
}
}
private static RangeObject GetInitialRange(List<RangeObject> rangeObjects)
{
int? start = null;
int? end = null;
foreach (var rangeObject in rangeObjects)
{
if (start == null || rangeObject.Start < start)
start = rangeObject.Start;
if (end == null || rangeObject.End > end)
end = rangeObject.End;
}
if (start == null || end == null)
return null;
return new RangeObject(start.Value, end.Value, new List<object>());
}
}
The following is one way to get rid of goto:
private List<RangeObject> UntangleRangeList(List<RangeObject> list)
{
List<RangeObject> list1 = new List<RangeObject>(list);
list1.Sort();
int start = 0;
while (!CheckSomething(list1, ref start)) ;
list1.Sort();
return list1;
}
private bool CheckSomething(List<RangeObject> list1, ref int start)
{
for (int i = start; i < list1.Count; i++)
{
for (int j = i + 1; j < list1.Count; j++)
{
if (list1[i].Start < list1[j].End && list1[j].Start < list1[i].End)
{
list1.AddRange(UntangleRanges(list1[i], list1[j]));
list1.Remove(list1[j]);
list1.Remove(list1[i]);
return false;
}
}
start++;
}
return true;
}

How can I add my data without "for" loop in my List?

There is a movies table. I added films of every customer to List. How can I add these elements of list without array to class that can receive inheritance from List<string>?
int sayici = 0;
for (int i = 0; i < filmler.Count; )
{
List<string> flm = new List<string>();
n = new varliklar.kisi_film_listesi();
for (int j = i + 1; j < (filmler.Count - 1); j++)
{
if (filmler[i]._CustomerID == filmler[j]._CustomerID)
{
flm.Add(filmler[j - 1]._Movie);
sayici++;
}
}
Veri nesneVeri = new Veri();
n._CumtomerID = filmler[i]._CustomerID;
n._movies = flm;
// I WANT TO CHANGE THIS "for" LOOP, I WANT TO ADD WITHOUT ARRAY
for (int a = 0; a < flm.Count; a++)
{
nesneVeri.Add(flm[a]);
}
db.Add(nesneVeri);
i += sayici + 1;
sayici = 0;
}
This is also my Data class below
public class Veri : List<String>
{
public double Destek { get; set; }
public bool Contains(Veri veriler)
{
return (this.Intersect(veriler).Count() == veriler.Count);
}
public Veri Remove(Veri veriler)
{
Veri removed = new Veri();
removed.AddRange(from item in this
where !veriler.Contains(item)
select item);
return (removed);
}
public override string ToString()
{
return ("{" + string.Join(", ", this.ToArray()) + "}" + (this.Destek > 0 ? " (Destek: " + Math.Round(this.Destek, 2) + "%)" : string.Empty));
}
Well this loop:
for (int a = 0; a < flm.Count; a++)
{
nesneVeri.Add(flm[a]);
}
is the same as:
nesneVeri.AddRange(flm);
The List<T>.AddRange function can take any IEnumerable<T>, so it will work with a list or an array. But I'm not sure what the actual issue is.
Because the class Veri inherits from List<string> you can use the AddRange method of the List class.
In your example, you can replace the for loop you want to change with this line of code.
nesneVeri.AddRange(flm)

Searching list by LastIndex in loop.

I am trying to complete an algorithm that adds ProcTime to a max of two other max values (JobNumMax and WSMax). I am having trouble using the FindLastIndex and FindLast in my loops.
Here is my code.
public class JobListOrder
{
public int JobNum { get; set; }
public string Workstation { get; set; }
public int Sequence { get; set; }
public int ProcTime { get; set; }
public int EndHour { get; set; }
public DateTime DueDate { get; set; }
public int Priority { get; set; }
}
Putting into list.
//New List
List<JobListOrder> list = new List<JobListOrder>();
using (StreamReader sr = new StreamReader("C:\\Users\\Nathan\\Documents\\Visual Studio 2013\\Projects\\PubsExample\\PubsExample\\JobsList.txt"))
{
//Add .txt to List
while (sr.Peek() >= 0)
{
string str;
string [] strArray;
str = sr.ReadLine();
strArray = str.Split(',');
JobListOrder currentjob = new JobListOrder();
currentjob.JobNum = int.Parse(strArray[0]);
currentjob.Workstation = strArray[1];
currentjob.Sequence = int.Parse(strArray[2]);
currentjob.ProcTime = int.Parse(strArray[3]);
currentjob.EndHour = int.Parse(strArray[4]);
currentjob.DueDate = DateTime.Parse(strArray[5]);
currentjob.Priority = int.Parse(strArray[6]);
list.Add(currentjob);
}
Sort into a particular way to start calculations
//Job Sort
var ListSort = from jobsort in list
orderby jobsort.Sequence ascending, jobsort.Priority descending, jobsort.DueDate ascending, jobsort.JobNum ascending
select jobsort;
List<JobListOrder> SortList = new List<JobListOrder>(ListSort);
Here is a slight attempt at it
//foreach (var i in SortList)
//{
// if (JobNumMax >= WSMax)
// {
// return i.EndHour = JobNumMax + i.ProcTime;
// }
// else
// return i.EndHour = WSMax + currentjob.ProcTime;
// for (var j = 0; j < SortList.Count; j++)
// {
// int JobLNumMaxIndex = SortList.FindLastIndex(i.JobNum)
// int JobNumMax = i.EndHour[JobNumMaxIndex];
// for (var k = 0; k < SortList.Count; k++)
// {
// int WSMaxIndex = SortList.FindLastIndex(i.Workstation);
// int WSMax = i.EndHour[JobNumMaxIndex];
// }
// }
//}
I am trying to find the LastIndex of a query and return a value of that particular index. I'll try to explain what I mean in the code below Searching for JobNum = 1 and Workstation = Milling with a ProcTime of 1
foreach (var i in SortList) //Iterate through SortList
{
if (JobNumMax (3) >= WSMax (4))
{
return i.EndHour = JobNumMax (3) + i.ProcTime (1); //assigns calculation to EndHour of current record
}
else
return i.EndHour = WSMax (4) + i.ProcTime (1);
for (var j = 0; j < SortList.Count; j++)
{
int JobLNumMaxIndex = SortList.FindLastIndex(1) //Finds last record with JobNum = 1
int JobNumMax = i.EndHour[JobNumMaxIndex];//Return what EndHour is at the index from JobNumMaxIndex search// Lets say 3
for (var k = 0; k < SortList.Count; k++)
{
int WSMaxIndex = SortList.FindLastIndex(Milling);//Finds last record with Workstation = Milling
int WSMax = i.EndHour[JobNumMaxIndex];//Return what EndHour is at the index from WSMaxIndex search// Lets say 4
}
}
}
Result would be 4 + 1 = 5.
I am having trouble with syntax of the algorithm. I can't get the FindLast to work at all.
It looks like you might just be having trouble with the LINQ syntax.
FindLastIndex will take a Predicate<JobListOrder> as an argument, i.e, a function which takes a JobListOrder as an input an returns true or false.
So instead of SortList.FindLastIndex(i.JobNum) you should probably have something like:
SortList.FindLastIndex(order => order.JobNum == i.JobNum);
Corrected in your code:
int JobNumMax = 0;
int WSMax 0;
foreach (var i in SortList)
{
if (JobNumMax >= WSMax)
{
return i.EndHour = JobNumMax + i.ProcTime;
}
else if (JobNumMax > 0 && WSMax > 0)
{
return i.EndHour = WSMax + currentjob.ProcTime;
}
for (var j = 0; j < SortList.Count; j++)
{
int JobLNumMaxIndex = SortList.FindLastIndex(order => order.JobNum == i.JobNum);
JobNumMax = i.EndHour[JobNumMaxIndex];
for (var k = 0; k < SortList.Count; k++)
{
int WSMaxIndex = SortList.FindLastIndex(order => order.Workstation == i.Workstation);
WSMax = i.EndHour[JobNumMaxIndex];
}
}
}

Count similar adjacent items in List<string>

I'm trying to find similar adjacent items in List and count its number, e.g.:
List<string> list = new List<string> {"a", "a", "b", "d", "c", "c"};
Desired Output:
a = 2, c = 2
What I've done is use for loop to iterate over each element of the list and to see whether it has similar adjacent element, but understandably it gives ArgumentOutOfRangeException() because I don't know how to keep track of the position of the iterator so that it doesn't go out of bounds. Here's what I've done:
for (int j = 0; j < list.Count; j++)
{
if (list[j] == "b")
{
if ((list[j + 1] == "b") && (list[j - 1] == "b"))
{
adjacent_found = true;
}
}
}
Having said that, if there's another easier way to find similar adjacent elements in a List other than using for loop iteration, please advise. Thanks.
You can do something like this:
static IEnumerable<Tuple<string, int>> FindAdjacentItems(IEnumerable<string> list)
{
string previous = null;
int count = 0;
foreach (string item in list)
{
if (previous == item)
{
count++;
}
else
{
if (count > 1)
{
yield return Tuple.Create(previous, count);
}
count = 1;
}
previous = item;
}
if (count > 1)
{
yield return Tuple.Create(previous, count);
}
}
for (int i= 0; i < list.Count; i++)
{
for (int j = i + 1; j < list.Count; j++)
{
if (list[i] == list[j])
{
adjacent_found = true;
count++;
}
}
}
Check this:
Dictionary<char,int> dic=new Dictionary<char,int>();
for(int i=1;i<list.count;i++)
{
if(list[i]==list[i-1])
{
if(dic.ContainsKey(list[i]))
{
dic[list[i]]+=1;
}
else
{
dic.Add(list[i],2)
}
}
}
To avoid ArgumentOutOfRangeException use for (int j = 1; j < list.Count - 1; j++). Desired answer can't be achieved this way. Try this:
IEnumerable<Adjacent> CountAdjacents(List<string> source)
{
var result = new List<Adjacent>();
for (var i = 0; i < source.Count() - 1; i++)
{
if (source[i] == source[i + 1])
{
if (result.Any(x => x.Word == source[i]))
{
result.Single(x => x.Word == source[i]).Quantity++;
}
else
result.Add(new Adjacent
{
Word = source[i],
Quantity = 2
});
}
}
return result;
}
class Adjacent
{
public string Word;
public int Quantity;
}
Maintain an int array of 256 size, initialized to 1. Run a loop [O(n)] for i=0 to i-2, compare each char with the next char. If same then find the ascii value of the char and increment the corresponding value in array.
Hope this helps!

Categories