Hi,
I have created a class which I user to create several list of different values. I am them going through all the list to count for frequency of the values. The problem is I want to consider say value1 = 1, value2 = 2, value3 = 3 to be the same as value1 = 2, value2 = 1, value3 = 3 and so on.

Now the way I am currently doing it is which a series of if statement which looks at the possibilities so for a my class called pair(below) I would swap the values around to look if they match. With a three value number I would have 5 possibities and so on.

I am just curious is there a fast way of seeing if the values match as I want them do without going through a number of If statments?

 public class MyDictionaryPair : Dictionary<int, Pair>
 {
    public void Add(int key, int value1, int value2, decimal weight1, decimal weight2, decimal totalWeight)
     {
         Pair val;
         val.Value1 = value1;
         val.Weight1 = weight1;
         val.Value2 = value2;
         val.Weight2 = weight2;
         val.TotalWeight = totalWeight;

        this.Add(key, val);
    }
}

Kind Regards

Your description is a bit vague.

What would a sample of the starting data look like?
What would a sample of the finished data to look like?
What code are you using to reorginize the data?

Edited 1 Year Ago by tinstaafl

`var listOfTriosFoundWithFrequency = new List<Tuple<int, Trio>>();`

`foreach (var trio in listOfTrios)
{
// Cycle through each trio to find out if we have the same trio already.
if (listOfFoundTrios.Contains(trio))
{
var oldTrio = new Tuple<int, Trio>(1, trio);
var newTrio = new Trio();
var oldFreq = 0;
var newFreq = 0;

//If so, we should expect this pair to have been added to the list considering its frequency
foreach (var foundTrio in listOfTriosFoundWithFrequency)
{
// Validate the two pairs to make sure they are identical
if (foundTrio.Item2.Value1 == trio.Value1 && foundTrio.Item2.Value2 == trio.Value2 && foundTrio.Item2.Value3 == trio.Value3)
{

// These trios are identical so lets get the old frequency and add one to it.
oldFreq = foundTrio.Item1;
newFreq = oldFreq + 1;

newTrio = foundTrio.Item2;

// These trio would need to be removed from the final list.
//triosToRemove.Add(foundTrio);
oldTrio = new Tuple<int, Trio>(foundTrio.Item1, foundTrio.Item2);
}
}

// As we have gone through the list we can now add the new pair and remove the old one
listOfTriosFoundWithFrequency.Add(new Tuple<int, Trio>(newFreq, newTrio));
listOfTriosFoundWithFrequency.Remove(oldTrio);
}

// If we haven't found the trio then we must add it to the list
else if (!listOfFoundTrios.Contains(trio))
{
listOfFoundTrios.Add(trio);
listOfTriosFoundWithFrequency.Add(new Tuple<int, Trio>(1, trio));
}
}
}

public struct Trio
{
public int Value1;
public decimal Weight1;
public int Value2;
public decimal Weight2;
public int Value3;
public decimal Weight3;
public decimal TotalWeight;
}

public class MyDictionaryTrio : Dictionary<int, Trio>
{
public void Add(int key, int value1, int value2, int value3, decimal weight1, decimal weight2, decimal weight3,decimal totalWeight)
{
Trio val;
val.Value1 = value1;
val.Weight1 = weight1;
val.Value2 = value2;
val.Weight2 = weight2;
val.Value3 = value3;
val.Weight3 = weight3;
val.TotalWeight = totalWeight;

this.Add(key, val);
}
}`

So this is my code so far. listOfTrios contains thousands of elements most of which are the same value. I go through each element to see if it is in another list called listOfFoundTrios. If it is then I want to add 1 to "frequency" and add the element to listOfTriosFoundWithFrequency and I also removed the old element and frequency from that list. If the trio is not the listOfFoundTrios, then I add it to that list as well as adding it to listOfTriosFoundWithFrequency giving it 1 for its frequency.

So ive tried added several If statments to look for different orders, for instances
if (foundTrio.Item2.Value1 == trio.Value2 && foundTrio.Item2.Value2 == trio.Value1 && foundTrio.Item2.Value3 == trio.Value3), but debugging proved that my program doesnt get to read this code plus its means I am writing simailr code 6 times (for the different orders).

So im trying to accomplish two things:

  1. Consider the different order of values to be the same.
  2. Not have to written code several times as i have list for pairs,trios,quad and pentas of values.

Hope thats clearer.

If I understand you right, you have sets of data and some sets may have the same data but in a different order and you want those sets to be treated as equal.

One way to accomplish this is with some refactoring. If we create a class to represent a datum pair we can easily have a class to represent a set of data. If we use a list to hold the individual data, this class can be used to represent varying sizes of data sets(3,4,5,etc.). This also allows us to override the Equals and GetHashCode methods to make the rest of our code much simpler:

public class Data_Set
{
    public class Datum
    {
        public int value;
        public decimal weight;
        private string _name;
        public string name
        {
            get
            {
                return _name;
            }
            set 
            {
                _name = value;
            }
        }
    }
    private const string nameBase = "Pair";
    private List<Datum> collection = new List<Datum>();
    public void AddDatum(int value, decimal weight)
    {
        Datum temp = new Datum { value = value, weight = weight, name = nameBase + collection.Count.ToString() };
        collection.Add(temp);
    }
    public override bool Equals(object obj)
    {
        return GetHashCode() == ((Data_Set)obj).GetHashCode();
    }
    public override int GetHashCode()
    {
        var retval = string.Join("", collection.Select(x => x.value).OrderBy(x => x));
        return retval.GetHashCode();
    }
    public static bool operator==(Data_Set lhs, Data_Set rhs)
    {
        return lhs.Equals(rhs);
    }
    public static bool operator !=(Data_Set lhs, Data_Set rhs)
    {
        return !lhs.Equals(rhs);
    }
}

Now to get a list of frequencies it's a simple matter of checking each Data_Set as it's read from the file with a Dictionary<Data_Set, int>. The ContainsKey method works well here:

Dictionary<Data_Set, int> frequencies = new Dictionary<Data_Set, int>();

    static void AddData_Set(Dictionary<Data_Set,int> freqs, Data_Set value)
    {
        if(freqs.ContainsKey(value))
        {
            freqs[value]++;
        }
        else
        {
            freqs.Add(value, 1);
        }
    }

As you read the data from the file, create a Data_Set and call the AddData_Set method to either increase the frequency count or add it to the collection.

Edited 1 Year Ago by tinstaafl

This article has been dead for over six months. Start a new discussion instead.