2014-05-10 7 views
8

द्वारा LINQ गैर-रैखिक क्रम क्रमबद्ध स्ट्रिंग की एक सूची प्राप्त करने का प्रयास कर रहा है जैसे कि सबसे लंबे समय तक सूची के अंत में हैं और सबसे कम मध्य में हैं। उदाहरण के लिए:स्ट्रिंग लंबाई

A 
BB 
CCC 
DDDD 
EEEEE 
FFFFFF 

अनुसार क्रमबद्ध जायेगा रूप में:

FFFFFF 
DDDD 
BB 
A 
CCC 
EEEEE 

संपादित करें: स्पष्ट करने के लिए, मैं विशेष रूप से वांछित परिणाम प्राप्त करने के लिए क्योंकि मुझे यकीन है कि नहीं था एक LINQ कार्यान्वयन के लिए देख रहा था कि कैसे/यदि LINQ का उपयोग करना संभव था।

उत्तर

7

मत पूछो कैसे और क्यों ... ^^

list.Sort(); // In case the list is not already sorted. 

var length = list.Count; 

var result = Enumerable.Range(0, length) 
         .Select(i => length - 1 - 2 * i) 
         .Select(i => list[Math.Abs(i - (i >> 31))]) 
         .ToList(); 

ठीक है, इससे पहले कि मैं भूल जाता हूं कि यह कैसे काम करता है, यहां आप जाते हैं।

उदाहरण के लिए 6 आइटम वाली एक सूची को इसके लिए पुन: व्यवस्थित किया जाना चाहिए; सबसे लंबी स्ट्रिंग इंडेक्स 5 पर है, जो कि पूर्व निर्धारित सूची के इंडेक्स 0 पर सबसे कम है।

5 3 1 0 2 4 

हम Enumerable.Range(0, length) उपज

0 1 2 3 4 5 

के साथ शुरू तो हम i => length - 1 - 2 * i लागू

5 3 1 -1 -3 -5 

उपज और हम गैर नकारात्मक हिस्सा सही है। अब ध्यान दें कि i >> 31 एक अंकगणित बाएं शिफ्ट है और साइन बिट को सभी बिट्स में कॉपी करेगा। इसलिए गैर-ऋणात्मक संख्या 0 उत्पन्न होती है जबकि ऋणात्मक संख्याएं उपज होती हैं -1। यही कारण है कि बदले में इसका मतलब घटाकर i >> 31 गैर नकारात्मक संख्या में बदलाव नहीं होगा लेकिन ऋणात्मक संख्याओं में 1 जोड़

5 3 1 0 -2 -4 

उपज और अब हम अंत में Math.Abs() लागू करते हैं और

5 3 1 0 2 4 

जो वांछित परिणाम प्राप्त होता है। यह विषम लंबाई की सूचियों के लिए समान रूप से काम करता है।

+0

प्रभावशाली उत्तर। – chad

+0

लेकिन कुछ भी नहीं जो आप उत्पादन कोड में रखना चाहते हैं। या शायद केवल * बहुत * टिप्पणियों के साथ। –

10

आप दो आदेश दिया समूह बना है, तो पहले समूह उतरते (पहले से ही किया जाता है) और दूसरे समूह आरोही क्रम सकता है:

var strings = new List<string> { 
     "A", 
     "BB", 
     "CCC", 
     "DDDD", 
     "EEEEE", 
     "FFFFFF"}; 
var two = strings.OrderByDescending(str => str.Length) 
     .Select((str, index) => new { str, index }) 
     .GroupBy(x => x.index % 2) 
     .ToList(); // two groups, ToList to prevent double execution in following query 
List<string> ordered = two.First() 
    .Concat(two.Last().OrderBy(x => x.str.Length)) 
    .Select(x => x.str) 
    .ToList(); 

परिणाम:

[0] "FFFFFF" string 
[1] "DDDD"  string 
[2] "BB"  string 
[3] "A"   string 
[4] "CCC"  string 
[5] "EEEEE"  string 
0

बस एक और विकल्प है, जो मैं अधिक पठनीय और पालन करने के लिए आसान लगता है: आप एक आदेश दिया सूची है: जहां आइटम ::

var new_list = new List<string>(); // This will hold your results 
bool start = true;     // Insert at head or tail 

foreach (var s in strings) 
{ 
    if (start) 
     new_list.Insert(0,s); 
    else   
     new_list.Add(s); 

    start = !start;    // Flip the insert location 
} 
जोड़ने

var strings = new List<string> { 
     "A", 
     "BB", 
     "CCC", 
     "DDDD", 
     "EEEEE", 
     "FFFFFF"}; 

बस वैकल्पिक नई सूची बनाएं और

मीठा और सरल :)

के लिए डैनियल ब्रकनर टिप्पणी के रूप में, अगर आप परवाह के बारे में जो तार आ सबसे पहले, आप प्रारंभ स्थिति को भी बदल सकते हैं:

// This will make sure the longest strings is first 
bool start= strings.Count()%2 == 1; 
+0

यह लंबाई की सूचियों के लिए एक तरह से बंद होगा - सबसे लंबी स्ट्रिंग अंतिम स्थिति में होगी। ठीक करें: 'var start = strings.Count% 2 == 1; ' –

+0

उन्होंने कहा कि' सूची के किसी भी अंत में सबसे लंबा 'है, फिर भी मेरी पुस्तक में काम करता है :)। मैं स्ट्रिंग को कहां रखना है, और KISS को गणना करने से बचाना चाहता था। – Noctis

+0

उचित बिंदु। अंत में मैंने यह पता लगाया कि मैं इसे उत्पादन कोड में कैसे कार्यान्वित करूंगा। –

संबंधित मुद्दे