0

I have three arrays like below:

   string[] shapeTypes = {"circle", "triangle", "square" };
   string[] shapeColor = { "red", "blue", "orange" };
   double[] shapeArea = { 20, 5, 4 };

I have to sort shapes by the value of their area (ascending order). For example the sorted arrays would be:

   shapeTypes = {"square", "triangle", "circle" };
   shapeColor = { "orange", "blue", "red" };
   shapeArea = { 4,5,20};

I tried Array.Sort method so far but it looks like it isn't working.

Array.Sort(shapeArea);
Array.Sort(shapeArea, shapeTypes);

Screenshot

Am I doing something wrong, or is there another way to sort the arrays?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
nuela
  • 35
  • 5
  • 5
    It's not clear what the relationship between `Types`, `Color` and `Area` is. You may consider whether or not you can use a [class](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/types/classes). If you use a class, see [Use the IComparable and IComparer interfaces in Visual CSharp](https://learn.microsoft.com/en-us/troubleshoot/developer/visualstudio/csharp/language-compilers/use-icomparable-icomparer). – Tu deschizi eu inchid Mar 02 '23 at 15:56
  • 2
    Please post all your code as copy-pasted text, not image(s). Having said that - if you first call `Sort` only with `shapeArea` (as the screenshot suggests) this array will be already in a different order and the second call to `Sort` will not have to modify it. You probably want only the 2nd call. – wohlstad Mar 02 '23 at 15:58
  • 1
    What you probably want is to have a `class Shape` with `Type`, `Color` and `Area` properties. That allows you to use LINQ and simply do `shapes = shapes.OrderBy(x => x.Area)`. – vgru Mar 02 '23 at 15:59
  • Are your 3 arrays related by their indexes ? I mean, do you have 'red circle 20', 'blue triangle 5' and 'orange square 4' ? If yes, considere using a class or a record with 3 attributes to represents a shape. – AoooR Mar 02 '23 at 16:00
  • `Sort()` sorts an array alphabetically by default. You are not using a comparer interface or anything like it to tell the method how to sort or the criteria to do it, so it sorted alphabetically. – javdromero Mar 02 '23 at 16:02
  • Related: [Sorting multiple arrays, based on the first array](https://stackoverflow.com/questions/29591992/sorting-multiple-arrays-c-sharp). – Theodor Zoulias Mar 02 '23 at 20:22

5 Answers5

1

The problem is that you call Sort twice:
After this 1st call:

Array.Sort(shapeArea);

shapeArea will be sorted, i.e.: {4, 5, 20).

Then the 2nd call:

Array.Sort(shapeArea, shapeTypes);

Will not change anything because shapeArea is already sorted.

Instead you should use only the 2nd call to sort both shapeArea and shapeTypes in synch.

Note:
Having said that, if you want to keep these 3 properties (type, color and area) in synch, a better approach would be to create a class to hold them.
Then use either Linq, or Array.Sort with a comparator for sorting (shown below).

Code example:

using System;

public class Program
{
    class Shape
    {
        public Shape(string type, string color, double area)
        {
            Type = type;
            Color = color;
            Area = area;
        }

        public string Type { get; set; }
        public string Color { get; set; }
        public double Area { get; set; }
    }

    public static void Main(String[] args)
    {
        Shape[] shapes =
        {
            new Shape("circle", "red", 20),
            new Shape("triangle", "blue", 5),
            new Shape("square", "orange", 4),
        };

        // Sort by area via a comparator:
        Array.Sort(shapes, (a, b) => a.Area.CompareTo(b.Area));
    }
}
wohlstad
  • 12,661
  • 10
  • 26
  • 39
1

Instead of having a separate array for each property, create a class combining all these properties. Then create a single array of this class:

// Naive implementation
public class Shape
{
    public string Type { get; set; }
    public string Color { get; set; }
    public double Area { get; set; }
}

This allows you to sort like this:

Shape[] shapes = {
    new Shape { Type = "circle", Color = "red", Area = 20 },
    new Shape { Type = "triangle", Color = "blue", Area = 5 },
    new Shape { Type = "square", Color = "orange", Area = 4 }
};

Array.Sort(shapes, (a, b) => a.Area.CompareTo(b.Area));

A better way to represent the shapes and colors is to use enums:

public enum ShapeType
{
    Circle,
    Triangle,
    Square
}

public enum ShapeColor
{
    Red,
    Blue,
    Green,
    Orange,
    // ...
}

And to implement the class like this

public class Shape
{
    public ShapeType Type { get; set; }
    public ShapeColor Color { get; set; }
    public double Area { get; set; }
}

A more advanced technique is to use inheritance to create different shapes:

public abstract class Shape
{
    public Color Color { get; set; }
    public abstract double Area { get; }
}

public class Circle : Shape
{
    public double Radius { get; set; }

    public override double Area => Radius * Radius * Math.PI;
}

public class Square : Shape
{
    public double Length { get; set; }

    public override double Area => Length * Length;
}

public class Triangle : Shape
{
    public double Height { get; set; }
    public double Base{ get; set; }

    public override double Area => Height * Base / 2;
}

I also use the Color Struct from the System.Drawing Namespace

Arrays have a fixed size. Using lists allows you to add, replace or remove shapes later. Example:

List<Shape> shapes = new() {
    new Circle { Color = Color.Red, Radius = 2.52 },
    new Triangle { Color = Color.Blue, Base = 4, Height = 2.5 },
    new Square { Color = Color.Orange, Length = 2 }
};

// Add a shape later
shapes.Add(new Circle { Color = Color.Yellow, Radius = 3 });

shapes.Sort((a, b) => a.Area.CompareTo(b.Area));
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
1

Here is a method that sorts three arrays of different types, based on the values in the first array. It allocates internally an int[] array, with size equal to the first array.

/// <summary>
/// Sorts three arrays, one contains the keys and the others contain
/// the corresponding items, based on the keys in the first array.
/// </summary>
public static void Sort<TKey, T1, T2>(TKey[] keys, T1[] items1, T2[] items2,
    IComparer<TKey> comparer = default)
{
    ArgumentNullException.ThrowIfNull(keys);
    ArgumentNullException.ThrowIfNull(items1);
    ArgumentNullException.ThrowIfNull(items2);
    if (items1.Length < keys.Length)
        throw new ArgumentException("Array too small.", nameof(items1));
    if (items2.Length < keys.Length)
        throw new ArgumentException("Array too small.", nameof(items2));
    comparer ??= Comparer<TKey>.Default;

    // Create an array of incremental indices (zero based).
    int[] indices = new int[keys.Length];
    for (int i = 0; i < indices.Length; i++) indices[i] = i;

    // Sort the indices according to the keys.
    Array.Sort<int>(indices, (x, y) => comparer.Compare(keys[x], keys[y]));

    // Sort all the arrays according to the indices.
    for (int i = 0; i < indices.Length - 1; i++)
    {
        int k = indices[i];
        while (k < i) k = indices[k];
        if (k == i) continue;
        // Swap the items in the positions i and k.
        Swap(keys, i, k);
        Swap(items1, i, k);
        Swap(items2, i, k);
    }

    static void Swap<T>(T[] array, int x, int y)
    {
        T temp = array[x];
        array[x] = array[y];
        array[y] = temp;
    }
}

Usage example:

Sort(shapeArea, shapeTypes, shapeColor);

Online demo.

I've used the same technique with the indices in this question: Sort array of integer-triples in C#.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
0

You can use SortedList<TKey,TValue>

SortedList<string, double> shapeTypeAreas = new SortedList<string, double>();
 
shapeTypeAreas.Add("circle",20);
shapeTypeAreas.Add("triangle", 5);
shapeTypeAreas.Add("square", 4); 
foreach( KeyValuePair<string, string> kvp in shapeTypeAreas )
{
  Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
}
0

You need to inspect the shapeTypes array after the Sort. Check the following:

        string[] shapeTypes = { "circle", "triangle", "square" };
        string[] shapeColor = { "red", "blue", "orange" };
        double[] shapeArea = { 20, 5, 4 };

        Array.Sort(shapeArea, shapeTypes);

        Console.WriteLine(shapeTypes);
        Console.WriteLine(shapeArea);
wakasupi
  • 54
  • 6