जब एक स्ट्रिंग संख्यात्मक होता है तो मैं मूल्य के लिए लेखांकन करते समय वर्णानुक्रम में तार कैसे छाँटता हूं?


100

मैं संख्याओं की एक श्रृंखला को सॉर्ट करने की कोशिश कर रहा हूं जो स्ट्रिंग हैं और मैं उन्हें संख्यात्मक रूप से सॉर्ट करना चाहूंगा।

पकड़ यह है कि मैं संख्याओं को इंट में नहीं बदल सकता

यहाँ कोड है:

string[] things= new string[] { "105", "101", "102", "103", "90" };

foreach (var thing in things.OrderBy(x => x))
{
    Console.WriteLine(thing);
}

आउटपुट: 101, 102, 103, 105, 90

मैं चाहूंगा: 90, 101, 102, 103, 105

संपादित करें: उत्पादन 090, 101, 102 नहीं हो सकता ...

"आकार" के बजाय "चीजें" कहने के लिए कोड नमूना अपडेट किया गया। सरणी कुछ इस तरह हो सकती है:

string[] things= new string[] { "paul", "bob", "lauren", "007", "90" };

इसका मतलब है कि इसे वर्णानुक्रम से और संख्या के आधार पर क्रमबद्ध किया जाना चाहिए:

007, 90, बॉब, लॉरेन, पॉल


8
आप उन्हें इंट में क्यों नहीं बदल सकते?
फेमरेफ

1
"आकार" कुछ और हो सकता है जैसे "नाम"। कोड नमूना सिर्फ सरलीकृत है।
एसएफ।

2
क्या कोई संख्या नकारात्मक होगी? क्या वे सभी पूर्णांक होंगे? पूर्णांकों की सीमा क्या है?
एरिक लिपर्ट

"चीजें" किसी भी प्रकार की स्ट्रिंग हो सकती हैं। मैं सूची को गैर कंप्यूटर साक्षर व्यक्ति को तार्किक रूप से क्रमबद्ध करना चाहूंगा। नकारात्मक संख्याएं पोस्टिव से पहले होनी चाहिए। स्ट्रिंग की लंबाई के संदर्भ में, यह 100 से अधिक आकर्षण नहीं होगा।
एसएफ।

5
आप कितनी दूर जाना चाहते हैं? के image10बाद आना चाहिए image2? Januaryपहले आना चाहिए February?
svick

जवाबों:


104

ऑर्डरबी में एक कस्टम तुलनाकर्ता पास करें। Enumerable.OrderBy आपको अपनी पसंद के किसी भी तुलना को निर्दिष्ट करने देगा।

यह ऐसा करने का एक तरीका है:

void Main()
{
    string[] things = new string[] { "paul", "bob", "lauren", "007", "90", "101"};

    foreach (var thing in things.OrderBy(x => x, new SemiNumericComparer()))
    {    
        Console.WriteLine(thing);
    }
}


public class SemiNumericComparer: IComparer<string>
{
    /// <summary>
    /// Method to determine if a string is a number
    /// </summary>
    /// <param name="value">String to test</param>
    /// <returns>True if numeric</returns>
    public static bool IsNumeric(string value)
    {
        return int.TryParse(value, out _);
    }

    /// <inheritdoc />
    public int Compare(string s1, string s2)
    {
        const int S1GreaterThanS2 = 1;
        const int S2GreaterThanS1 = -1;

        var IsNumeric1 = IsNumeric(s1);
        var IsNumeric2 = IsNumeric(s2);

        if (IsNumeric1 && IsNumeric2)
        {
            var i1 = Convert.ToInt32(s1);
            var i2 = Convert.ToInt32(s2);

            if (i1 > i2)
            {
                return S1GreaterThanS2;
            }

            if (i1 < i2)
            {
                return S2GreaterThanS1;
            }

            return 0;
        }

        if (IsNumeric1)
        {
            return S2GreaterThanS1;
        }

        if (IsNumeric2)
        {
            return S1GreaterThanS2;
        }

        return string.Compare(s1, s2, true, CultureInfo.InvariantCulture);
    }
}

1
दिए गए इनपुट के लिए, यह पुनरावर्ती के उत्तर के समान परिणाम उत्पन्न करता है, जिसमें PadLeft () शामिल है। मैं मान रहा हूँ कि आपका इनपुट वास्तव में इस उदाहरण शो से अधिक जटिल है, जिस स्थिति में एक कस्टम तुलना जाने का तरीका है।
जेफ पॉलसन

चीयर्स। यह समाधान काम करता है और इसे पढ़ने में आसान और लागू करने का आसान तरीका लगता है। मुझे दिखाने के लिए +1 आप ऑर्डरबाय पर IComparer का उपयोग कर सकते हैं :)
sf।

17
IsNumericविधि बुरा है, कोडिंग संचालित एक अपवाद हमेशा बुरा है। int.TryParseइसके बजाय उपयोग करें । एक बड़ी सूची के साथ अपना कोड आज़माएं और इसे हमेशा के लिए ले जाएगा।
निन डेर थाल

यदि यह मददगार है, तो मैंने इस संस्करण में यहां एक एक्सटेंशन जोड़ा जो शब्दों के साथ छंटाई के लिए समर्थन जोड़ता है। मेरी जरूरतों के लिए, रिक्त स्थान पर विभाजन पर्याप्त था, और मुझे मिश्रित उपयोग के शब्दों (जैसे test12 बनाम test3) के बारे में चिंता करने की बहुत कम आवश्यकता थी,
mat.bungard

यदि आप डिबगिंग कर रहे हैं या आप अपवाद ऑब्जेक्ट एक्सेस कर रहे हैं, तो @NeanDerThal मुझे पूरा यकीन है कि यह केवल धीमी / खराब हैंडलिंग के बहुत सारे काम है।
केली एल्टन

90

ज़ीरो के साथ बस उसी लंबाई में पैड:

int maxlen = sizes.Max(x => x.Length);
var result = sizes.OrderBy(x => x.PadLeft(maxlen, '0'));

सरल समाधान के लिए +1, नाइटपैकिंग (पहले से ही संपादन में, अच्छा)
Marino Šimić

अच्छा विचार है लेकिन अगली पकड़ यह है कि मुझे इन मूल्यों को कूटनीतिक बनाने की आवश्यकता है इसलिए "90" को "90" होना चाहिए, न कि "090"
sf।

6
@ एसएफ: यह कोशिश करो, आप परिणाम पसंद कर सकते हैं। याद रखें, ऑर्डर की कुंजी ऑर्डर की जाने वाली चीज नहीं है। अगर मैंने अंतिम नाम से ग्राहकों की सूची का आदेश देने के लिए कहा है, तो मुझे ग्राहकों की एक सूची मिलती है, न कि अंतिम नामों की सूची। यदि आप एक परिवर्तित स्ट्रिंग द्वारा तारों की सूची का आदेश देने के लिए कहते हैं, तो परिणाम मूल तारों की क्रमबद्ध सूची है, न कि बदले गए तार।
एरिक लिपर्ट

मुझे इस काम को करने के लिए "size = size.OrderBy (...)" को जोड़ना पड़ा। क्या यह सामान्य है या उत्तर को संपादित किया जाना चाहिए?
गोरगाबल

1
@gorgabal: सामान्य री-असाइनिंग में sizesकाम नहीं करेगा, क्योंकि परिणाम एक अलग प्रकार है। इसका जवाब शॉर्ट-हैंड में है, जिसमें दूसरी पंक्ति एक अभिव्यक्ति के रूप में परिणाम दिखाती है, लेकिन यह पाठक के ऊपर है कि वह इसके बारे में कुछ करे। मैंने एक और वैरिएबल असाइनमेंट जोड़ा है ताकि इसे और अधिक स्पष्ट किया जा सके।
पुनरावर्ती

74

और, इस बारे में कैसे ...

string[] sizes = new string[] { "105", "101", "102", "103", "90" };

var size = from x in sizes
           orderby x.Length, x
           select x;

foreach (var p in size)
{
    Console.WriteLine(p);
}

हे, मैं वास्तव में इस एक को पसंद करता हूं - बहुत चालाक। क्षमा करें, यदि मैंने प्रारंभिक डेटा का पूरा सेट प्रदान नहीं किया है
sf।

3
यह केवल बेहतर आईएमओ के ऊपर पैड विकल्प की तरह है।
dudeNumber4

3
var आकार = size.OrderBy (x => x.Length) .ThenBy (x => x);
फिलिप डेविस

1
लेकिन यह इस तरह से अल्फाबेटिक स्ट्रिंग्स को मिलाएगा "b", "ab", "101", "103", "bob", "abcd":।
एंड्रयू

67

मान एक स्ट्रिंग है

List = List.OrderBy(c => c.Value.Length).ThenBy(c => c.Value).ToList();

काम करता है


2
यह उत्तर मेरा पसंदीदा है।
LacOniC

2
धन्यवाद, मुझे पता चलता है कि एक "तब" विधि से बाहर निकलता है।
ganchito55

यह मेरे उपयोग के मामले के लिए बहुत अच्छा काम करता है, जहाँ इनपुट नए प्रारूप में हैstring[] { "Object 1", "Object 9", "Object 14" }
Thelem

2
यह सबसे अच्छा जवाब है। यह काम करता है और एक अच्छी सीख है। धन्यवाद !!
जुलाईऑर्डिनरी

1
लेकिन यह इस तरह से अल्फाबेटिक स्ट्रिंग्स को मिलाएगा "b", "ab", "101", "103", "bob", "abcd":।
एंड्रयू

13

खिड़कियों में एक मूल कार्य है StrCmpLogicalWजो अक्षरों के बजाय संख्याओं के रूप में तार संख्याओं की तुलना करेगा। तुलना करना आसान है जो उस फ़ंक्शन को कॉल करता है और इसकी तुलना करता है।

public class StrCmpLogicalComparer : Comparer<string>
{
    [DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
    private static extern int StrCmpLogicalW(string x, string y);

    public override int Compare(string x, string y)
    {
        return StrCmpLogicalW(x, y);
    }
}

यह उन स्ट्रिंग्स पर भी काम करता है जिनमें टेक्स्ट और नंबर दोनों होते हैं। यहाँ एक उदाहरण कार्यक्रम है कि डिफ़ॉल्ट सॉर्ट और के बीच diffrence दिखाएगा StrCmpLogicalWप्रकार

class Program
{
    static void Main()
    {
        List<string> items = new List<string>()
        {
            "Example1.txt", "Example2.txt", "Example3.txt", "Example4.txt", "Example5.txt", "Example6.txt", "Example7.txt", "Example8.txt", "Example9.txt", "Example10.txt",
            "Example11.txt", "Example12.txt", "Example13.txt", "Example14.txt", "Example15.txt", "Example16.txt", "Example17.txt", "Example18.txt", "Example19.txt", "Example20.txt"
        };

        items.Sort();

        foreach (var item in items)
        {
            Console.WriteLine(item);
        }

        Console.WriteLine();

        items.Sort(new StrCmpLogicalComparer());

        foreach (var item in items)
        {
            Console.WriteLine(item);
        }
        Console.ReadLine();
    }
}

जो आउटपुट देता है

Example1.txt
Example10.txt
Example11.txt
Example12.txt
Example13.txt
Example14.txt
Example15.txt
Example16.txt
Example17.txt
Example18.txt
Example19.txt
Example2.txt
Example20.txt
Example3.txt
Example4.txt
Example5.txt
Example6.txt
Example7.txt
Example8.txt
Example9.txt

Example1.txt
Example2.txt
Example3.txt
Example4.txt
Example5.txt
Example6.txt
Example7.txt
Example8.txt
Example9.txt
Example10.txt
Example11.txt
Example12.txt
Example13.txt
Example14.txt
Example15.txt
Example16.txt
Example17.txt
Example18.txt
Example19.txt
Example20.txt

मैं चाहता हूं कि
काइल डेलाने

यह सही होगा, लेकिन यह दुर्भाग्य से नकारात्मक संख्या को संभाल नहीं सकता है। -1 0 10 2के रूप में क्रमबद्ध है0 -1 2 10
nphx

5

इसे इस्तेमाल करे

sizes.OrderBy(x => Convert.ToInt32(x)).ToList<string>();

नोट: यह तब सहायक होगा जब सभी स्ट्रिंग को परिवर्तनीय हो .....


1
इस थोड़े स्ट्रिंग को एक इंट में परिवर्तित करता है।
फेमरेफ

1
"आकार" गैर-संख्यात्मक भी हो सकता है
sf।

"LINQ to SQL" से ToList()पहले =>sizes.ToList().OrderBy(x => Convert.ToInt32(x))
A. Morel

5

मुझे लगता है कि यदि स्ट्रिंग में कुछ संख्यात्मक है तो यह बहुत अधिक अच्छा होगा। आशा है कि यह मदद करेगा।

पुनश्च: मैं प्रदर्शन या जटिल स्ट्रिंग मूल्यों के बारे में निश्चित नहीं हूं लेकिन इसने कुछ अच्छा काम किया है:

lorem ipsum
lorem ipsum 1
लोरेम ipsum 2
लोरेम ipsum 3
...
lorem ipsum 20
लोरेम ipsum 21

public class SemiNumericComparer : IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        int s1r, s2r;
        var s1n = IsNumeric(s1, out s1r);
        var s2n = IsNumeric(s2, out s2r);

        if (s1n && s2n) return s1r - s2r;
        else if (s1n) return -1;
        else if (s2n) return 1;

        var num1 = Regex.Match(s1, @"\d+$");
        var num2 = Regex.Match(s2, @"\d+$");

        var onlyString1 = s1.Remove(num1.Index, num1.Length);
        var onlyString2 = s2.Remove(num2.Index, num2.Length);

        if (onlyString1 == onlyString2)
        {
            if (num1.Success && num2.Success) return Convert.ToInt32(num1.Value) - Convert.ToInt32(num2.Value);
            else if (num1.Success) return 1;
            else if (num2.Success) return -1;
        }

        return string.Compare(s1, s2, true);
    }

    public bool IsNumeric(string value, out int result)
    {
        return int.TryParse(value, out result);
    }
}

ठीक वही जो मेरे द्वारा खोजा जा रहा था। धन्यवाद!
klugerama

4

आप कहते हैं कि आप संख्याओं को int में नहीं बदल सकते क्योंकि सरणी में ऐसे तत्व हो सकते हैं जिन्हें int में परिवर्तित नहीं किया जा सकता है, लेकिन कोशिश करने में कोई बुराई नहीं है:

string[] things = new string[] { "105", "101", "102", "103", "90", "paul", "bob", "lauren", "007", "90" };
Array.Sort(things, CompareThings);

foreach (var thing in things)
    Debug.WriteLine(thing);

फिर इस तरह की तुलना करें:

private static int CompareThings(string x, string y)
{
    int intX, intY;
    if (int.TryParse(x, out intX) && int.TryParse(y, out intY))
        return intX.CompareTo(intY);

    return x.CompareTo(y);
}

आउटपुट: 007, 90, 90, 101, 102, 103, 105, बॉब, लॉरेन, पॉल


Btw, मैंने सादगी के लिए Array.Sort का उपयोग किया, लेकिन आप एक IComparer में एक ही तर्क का उपयोग कर सकते हैं और OrderBy का उपयोग कर सकते हैं।
उल्फ क्रिस्टियानसेन

IComparer (मेरी राय) का उपयोग करते हुए यह समाधान तेजी से लगता है। 15000 परिणाम और मुझे लगता है कि यह एक दूसरे अंतर के बारे में है।
जेसन फोगलिया

3

यह एक अजीब अनुरोध लगता है और एक अजीब समाधान के योग्य है:

string[] sizes = new string[] { "105", "101", "102", "103", "90" };

foreach (var size in sizes.OrderBy(x => {
    double sum = 0;
    int position = 0;
    foreach (char c in x.ToCharArray().Reverse()) {
        sum += (c - 48) * (int)(Math.Pow(10,position));
        position++;
    }
    return sum;
}))

{
    Console.WriteLine(size);
}

मेरा मतलब 0x30 था। इसके अलावा, सरणी में अभी भी एक गैर-संख्यात्मक स्ट्रिंग हो सकती है, जिसके लिए समाधान दिलचस्प परिणाम देगा।
फेमारेफ

और ध्यान दें कि -48 या बिल्कुल नहीं बदलता है, हम सीधे चार्जर के पूर्णांक मूल्य का उपयोग कर सकते हैं, इसलिए उस -48 को हटा दें यदि यह आपको परेशान करता है ...
Marino ćimić

चार मान 0x30 है, यदि आप इसे int में बदलते हैं, तो यह 0x30 होगा, जो कि नंबर 0. नहीं है
Femaref

केवल एक चीज जो पूर्णांक में परिवर्तित होती है, वह डबल है जो Math.Pow से वापस आ जाती है
Marino

यदि यह शून्य है या नहीं, तो महिला संबंधी कोई बात नहीं करता है, डिकैडिक सिस्टम इस बात का ध्यान रखता है, यह एक to हो सकता है यदि आप चाहते हैं, केवल एक चीज जो मायने रखती है कि वर्ण सेट में आरोही क्रम में हैं, और वह कम है 10 से
मैरिनो 10imić

3

यह साइट अल्फ़ान्यूमेरिक सॉर्टिंग पर चर्चा करती है और ASCII अर्थ के बजाय तार्किक अर्थ में संख्याओं को सॉर्ट करेगी। इसके आसपास के अल्फाजों को भी ध्यान में रखता है:

http://www.dotnetperls.com/alphanumeric-sorting

उदाहरण:

  • सी: /TestB/333.jpg
  • 1 1
  • सी: /TestB/33.jpg
  • 1
  • सी: /TestA/111.jpg
  • 111F
  • सी: /TestA/11.jpg
  • 2
  • सी: /TestA/1.jpg
  • 111D
  • 22
  • 111Z
  • सी: /TestB/03.jpg

  • 1
  • 2
  • 1 1
  • 22
  • 111D
  • 111F
  • 111Z
  • सी: /TestA/1.jpg
  • सी: /TestA/11.jpg
  • सी: /TestA/111.jpg
  • सी: /TestB/03.jpg
  • सी: /TestB/33.jpg
  • सी: /TestB/333.jpg

कोड इस प्रकार है:

class Program
{
    static void Main(string[] args)
    {
        var arr = new string[]
        {
           "C:/TestB/333.jpg",
           "11",
           "C:/TestB/33.jpg",
           "1",
           "C:/TestA/111.jpg",
           "111F",
           "C:/TestA/11.jpg",
           "2",
           "C:/TestA/1.jpg",
           "111D",
           "22",
           "111Z",
           "C:/TestB/03.jpg"
        };
        Array.Sort(arr, new AlphaNumericComparer());
        foreach(var e in arr) {
            Console.WriteLine(e);
        }
    }
}

public class AlphaNumericComparer : IComparer
{
    public int Compare(object x, object y)
    {
        string s1 = x as string;
        if (s1 == null)
        {
            return 0;
        }
        string s2 = y as string;
        if (s2 == null)
        {
            return 0;
        }

        int len1 = s1.Length;
        int len2 = s2.Length;
        int marker1 = 0;
        int marker2 = 0;

        // Walk through two the strings with two markers.
        while (marker1 < len1 && marker2 < len2)
        {
            char ch1 = s1[marker1];
            char ch2 = s2[marker2];

            // Some buffers we can build up characters in for each chunk.
            char[] space1 = new char[len1];
            int loc1 = 0;
            char[] space2 = new char[len2];
            int loc2 = 0;

            // Walk through all following characters that are digits or
            // characters in BOTH strings starting at the appropriate marker.
            // Collect char arrays.
            do
            {
                space1[loc1++] = ch1;
                marker1++;

                if (marker1 < len1)
                {
                    ch1 = s1[marker1];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch1) == char.IsDigit(space1[0]));

            do
            {
                space2[loc2++] = ch2;
                marker2++;

                if (marker2 < len2)
                {
                    ch2 = s2[marker2];
                }
                else
                {
                    break;
                }
            } while (char.IsDigit(ch2) == char.IsDigit(space2[0]));

            // If we have collected numbers, compare them numerically.
            // Otherwise, if we have strings, compare them alphabetically.
            string str1 = new string(space1);
            string str2 = new string(space2);

            int result;

            if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
            {
                int thisNumericChunk = int.Parse(str1);
                int thatNumericChunk = int.Parse(str2);
                result = thisNumericChunk.CompareTo(thatNumericChunk);
            }
            else
            {
                result = str1.CompareTo(str2);
            }

            if (result != 0)
            {
                return result;
            }
        }
        return len1 - len2;
    }
}

2

जेफ पॉलसन द्वारा दिया गया उत्तर सही है लेकिन Comprarerइसे बहुत सरल बनाया जा सकता है:

public class SemiNumericComparer: IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        if (IsNumeric(s1) && IsNumeric(s2))
          return Convert.ToInt32(s1) - Convert.ToInt32(s2)

        if (IsNumeric(s1) && !IsNumeric(s2))
            return -1;

        if (!IsNumeric(s1) && IsNumeric(s2))
            return 1;

        return string.Compare(s1, s2, true);
    }

    public static bool IsNumeric(object value)
    {
        int result;
        return Int32.TryParse(value, out result);
    }
}

यह काम करता है क्योंकि परिणाम के लिए जाँच की जाती है कि केवल एक चीज है Comparer है यदि परिणाम बड़ा, छोटा या शून्य के बराबर है। कोई बस दूसरे से मूल्यों को घटा सकता है और रिटर्न मानों को संभालने के लिए नहीं है।

साथ ही IsNumericविधि को try-ब्लॉक का उपयोग नहीं करना चाहिए और इससे लाभ हो सकता है TryParse

और उन लोगों के लिए जो यह सुनिश्चित नहीं कर रहे हैं: यह तुलना मूल्यों को छाँटेगी, ताकि गैर-संख्यात्मक मान हमेशा सूची के अंत में संलग्न हों। अगर कोई उन्हें शुरुआत में चाहता है तो दूसरे और तीसरे ifब्लॉक को स्वैप करना होगा।


जैसा कि TryParse पद्धति को कॉल करने पर संभवतः कुछ ओवरहेड होता है, मैं पहले s1 और s2 के लिए समसामयिक मानों को बूलियन मूल्यों में संग्रहीत करता हूं और इसके बजाय उन पर तुलना करता हूं। इस तरह उनका कई बार मूल्यांकन नहीं किया जाता है।
Optavius

1

इसे इस्तेमाल करे :

string[] things= new string[] { "105", "101", "102", "103", "90" };

int tmpNumber;

foreach (var thing in (things.Where(xx => int.TryParse(xx, out tmpNumber)).OrderBy(xx =>     int.Parse(xx))).Concat(things.Where(xx => !int.TryParse(xx, out tmpNumber)).OrderBy(xx => xx)))
{
    Console.WriteLine(thing);
}

1
public class NaturalSort: IComparer<string>
{
          [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
          public static extern int StrCmpLogicalW(string x, string y);

          public int Compare(string x, string y)
          {
                 return StrCmpLogicalW(x, y);
          }
}

arr = arr.OrderBy (x => x, new NaturalSort ())। ToArray ();

इसका कारण यह है कि मुझे एक निर्देशिका में दाखिल होना था जिसका नाम एक नंबर से शुरू हुआ था:

public static FileInfo[] GetFiles(string path)
{
  return new DirectoryInfo(path).GetFiles()
                                .OrderBy(x => x.Name, new NaturalSort())
                                .ToArray();
}

0
Try this out..  



  string[] things = new string[] { "paul", "bob", "lauren", "007", "90", "-10" };

        List<int> num = new List<int>();
        List<string> str = new List<string>();
        for (int i = 0; i < things.Count(); i++)
        {

            int result;
            if (int.TryParse(things[i], out result))
            {
                num.Add(result);
            }
            else
            {
                str.Add(things[i]);
            }


        }

अब सूची को क्रमबद्ध करें और उन्हें वापस मर्ज करें ...

        var strsort = from s in str
                      orderby s.Length
                      select s;

        var numsort = from n in num
                     orderby n
                     select n;

        for (int i = 0; i < things.Count(); i++)
        {

         if(i < numsort.Count())
             things[i] = numsort.ElementAt(i).ToString();
             else
             things[i] = strsort.ElementAt(i - numsort.Count());               
               }

मैं jsut ने इस दिलचस्प सवाल में योगदान देने की कोशिश की ...


0

मेरा पसंदीदा समाधान (यदि सभी तार केवल संख्यात्मक हैं):

// Order by numerical order: (Assertion: all things are numeric strings only) 
foreach (var thing in things.OrderBy(int.Parse))
{
    Console.Writeline(thing);
}

0
public class Test
{
    public void TestMethod()
    {
        List<string> buyersList = new List<string>() { "5", "10", "1", "str", "3", "string" };
        List<string> soretedBuyersList = null;

        soretedBuyersList = new List<string>(SortedList(buyersList));
    }

    public List<string> SortedList(List<string> unsoredList)
    {
        return unsoredList.OrderBy(o => o, new SortNumericComparer()).ToList();
    }
}

   public class SortNumericComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        int xInt = 0;
        int yInt = 0;
        int result = -1;

        if (!int.TryParse(x, out xInt))
        {
            result = 1;
        }

        if(int.TryParse(y, out yInt))
        {
            if(result == -1)
            {
                result = xInt - yInt;
            }
        }
        else if(result == 1)
        {
             result = string.Compare(x, y, true);
        }

        return result;
    }
}

क्या आप अपना कोड समझा सकते हैं ? कोड-केवल उत्तर हटाए जाने योग्य हैं।
वाई हा ली

जेफ पॉलसेन पोस्ट ने मुझे मेरे बोरिंग मुद्दे को ठीक करने के लिए IComparer <string> को लागू करने में मदद की। ।
कुमार 13

0

जेफ पॉलसन के जवाब पर विस्तार। मैं यह सुनिश्चित करना चाहता था कि स्ट्रिंग्स में कितने नंबर या चार समूह हों, इससे कोई फर्क नहीं पड़ता:

public class SemiNumericComparer : IComparer<string>
{
    public int Compare(string s1, string s2)
    {
        if (int.TryParse(s1, out var i1) && int.TryParse(s2, out var i2))
        {
            if (i1 > i2)
            {
                return 1;
            }

            if (i1 < i2)
            {
                return -1;
            }

            if (i1 == i2)
            {
                return 0;
            }
        }

        var text1 = SplitCharsAndNums(s1);
        var text2 = SplitCharsAndNums(s2);

        if (text1.Length > 1 && text2.Length > 1)
        {

            for (var i = 0; i < Math.Max(text1.Length, text2.Length); i++)
            {

                if (text1[i] != null && text2[i] != null)
                {
                    var pos = Compare(text1[i], text2[i]);
                    if (pos != 0)
                    {
                        return pos;
                    }
                }
                else
                {
                    //text1[i] is null there for the string is shorter and comes before a longer string.
                    if (text1[i] == null)
                    {
                        return -1;
                    }
                    if (text2[i] == null)
                    {
                        return 1;
                    }
                }
            }
        }

        return string.Compare(s1, s2, true);
    }

    private string[] SplitCharsAndNums(string text)
    {
        var sb = new StringBuilder();
        for (var i = 0; i < text.Length - 1; i++)
        {
            if ((!char.IsDigit(text[i]) && char.IsDigit(text[i + 1])) ||
                (char.IsDigit(text[i]) && !char.IsDigit(text[i + 1])))
            {
                sb.Append(text[i]);
                sb.Append(" ");
            }
            else
            {
                sb.Append(text[i]);
            }
        }

        sb.Append(text[text.Length - 1]);

        return sb.ToString().Split(' ');
    }
}

मैं भी एक से SplitCharsAndNums ले लिया फ़ाइल नामों से निपटने के लिए इसे संशोधित करने के बाद एसओ पृष्ठ


-1

हालांकि यह एक पुराना सवाल है, मैं एक समाधान देना चाहूंगा:

string[] things= new string[] { "105", "101", "102", "103", "90" };

foreach (var thing in things.OrderBy(x => Int32.Parse(x) )
{
    Console.WriteLine(thing);
}

वोहा बिलकुल सरल? : डी


-1
namespace X
{
    public class Utils
    {
        public class StrCmpLogicalComparer : IComparer<Projects.Sample>
        {
            [DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
            private static extern int StrCmpLogicalW(string x, string y);


            public int Compare(Projects.Sample x, Projects.Sample y)
            {
                string[] ls1 = x.sample_name.Split("_");
                string[] ls2 = y.sample_name.Split("_");
                string s1 = ls1[0];
                string s2 = ls2[0];
                return StrCmpLogicalW(s1, s2);
            }
        }

    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.