开发者

Regarding Sorting MultiDimensional Arrays in C#

开发者 https://www.devze.com 2023-04-05 03:23 出处:网络
I am trying to figure out a way to correctly sort a bunch of different arraylists. I am publishing content articles and every value [0] in an arraylist will relate to every other value [0]. and so on

I am trying to figure out a way to correctly sort a bunch of different arraylists. I am publishing content articles and every value [0] in an arraylist will relate to every other value [0]. and so on. Each element makes up the collective parts of a complete content item.

Now, the last element, popularity, is the amount of clicks an item has received. How do I do a sort of the content items based on popularity without mixing up the html for each article?

*开发者_StackOverflow中文版EDIT I am limited by the .NET 2.0 Framework at Work*

Below is the code... thanks.

public class MultiDimDictList : Dictionary<string, ArrayList> { } 

myDicList.Add("fly", a_fly);
myDicList.Add("img", a_img);
myDicList.Add("bar", a_bar);
myDicList.Add("meter", a_meter);
myDicList.Add("block", a_block);
myDicList.Add("popularity", a_pop);


If you use the following code you can convert your existing dictionary of arraylists into a collection of Dictionaries and thus allowing a simple sort using Linq OrderBy

// Get the shortest arraylist length (they should be equal this is just a paranoia check!)
var count=myDicList.Values.Min(x=>x.Count); 
// Get the collection of Keys
var keys=myDicList.Keys;
// Perform the conversion
var result=Enumerable.Range(0,count).Select(i=>keys.Select(k=>new {Key=k,Value=myDicList[k][i]}).ToDictionary(x=>x.Key,x=>x.Value)); 

var sorted=result.OrderByDescending(x=>x["popularity"]).ToList()

-- EDIT VERSION FOR .NET 2.0

First you need a comparer class

class PopularityComparison : IComparer<Dictionary<string,object>> {
    private bool _sortAscending;

    public PopularityComparison(bool sortAscending) {
        _sortAscending = sortAscending;
    }

    public int Compare(Dictionary<string, object> x, Dictionary<string, object> y) {
        object xValue = x["popularity"];
        object yValue = y["popularity"];

        // Sort Ascending
        if (_sortAscending) {
            return Comparer.Default.Compare(xValue, yValue);
        } else {
            return Comparer.Default.Compare(yValue, xValue);
        }

    }
}

Then you can use the following code

// Get the shortest arraylist length (they should be equal this is just a paranoia check!) 
// Replacement for min 
int count = int.MaxValue;
foreach (ArrayList a in myDicList.Values) if (a.Count < count) count = a.Count;
// Get the collection of Keys 
Dictionary<string, ArrayList>.KeyCollection keys = myDicList.Keys;
// Perform the conversion 
List<Dictionary<string, object>> result = new List<Dictionary<string, object>>(count);
for (int i = 0; i < count; i++) {
  Dictionary<string, object> row = new Dictionary<string, object>(keys.Count);
  foreach (string key in keys) row.Add(key, myDicList[key][i]);
  result.Add(row);
}

And then finally to sort in ascending popularity order

result.Sort(new PopularityComparison(true));

or Descending order

result.Sort(new PopularityComparison(true));


I'd think it would be better to have an object containing your keys as properties, then a single collection with each item you'd have in your array lists.

This way you'd have a single collection sort, which becomes trivial if using Linq.OrderBy().

something like...

public class Article
{
   public string Fly{get;set;}
   public string Img{get;set;}
   // etc.
   public float Popularity{get;set;}
}

Then...

List<Article> articles = ... get from somewhere, or convert from your array lists.
List<Article> sorted = articles.OrderBy(a=>a.Popularity).ToList();

Please excuse the napkin code here... I'll update it if you need more detail.

An example using non-linq.

Create an implementation of IComparer.

public class ArticleComparer : IComparer<Article>
{
    public bool Accending { get; set; }

    public int Compare(Article x, Article y)
    {
        float result = x.Popularity - y.Popularity;

        if (!Accending) { result *= -1; }

        if (result == 0) { return 0; }
        if (result > 0) return 1;
        return -1;
    }
}

Then when you go to sort the List, you can do something like the following.

ArticleComparer comparer = new ArticleComparer();
comparer.Accending = false;
articles.Sort(comparer);


This would be much easier if you had a list of article objects, each of which contained properties for fly, img, bar, popularity, etc. But if you really have to store things using this inside-out approach, then the only way you can sort the content items based on popularity is to create another array (or list) to hold the order.

Create a new list and populate it with sequential indexes:

List<int> OrderedByPopularity = new List<int>();
ArrayList popList = myDicList["popularity"];
for (int i = 0; i < popList.Count; ++i)
{
    OrderedByPopularity.Add(i);
}

Now you have a list that contains the indexes of the items in the popularity list. Now you can sort:

OrderedByPopularity.Sort((i1, i2) => return popList[i1].CompareTo(popList[i2]););

But that gives you the least popular article first. If you want to reverse the sort so that OrderedByPopularity[0] is the most popular item:

OrderedByPopularity.Sort((i1, i2) => { return popList[i2].CompareTo(popList[i1]);});

Really, though, you should look into restructuring your application. It's much easier to work with objects that have properties rather than trying to maintain parallel arrays of properties.

If you have to do this in .NET 2.0, declare the poplist array at class scope (rather than method scope), and create a comparison method.

ArrayList poplist;
void MyMethod()
{
    List<int> OrderedByPopularity = new List<int>();
    popList = myDicList["popularity"];
    for (int i = 0; i < popList.Count; ++i)
    {
        OrderedByPopularity.Add(i);
    }
    OrderedByPopularity.Sort(PopularityComparison);
    // ...
}

int PopularityComparison(int i1, int i2)
{
    return ((int)popList[i2]).CompareTo((int)popList[i1]);
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号