www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How would I sort an associative array by value?

reply "ixid" <nuaccount gmail.com> writes:
Or more generally does D have a library function so I can sort 
one array based on sorting the contents of another? I don't want 
to just sort the values alone, the associated keys would need to 
move with them. I can think of ways of doing it myself, just 
wondering if there's an elegant way built in.
Jun 29 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/29/2012 07:52 PM, ixid wrote:
 Or more generally does D have a library function so I can sort one array
 based on sorting the contents of another?

sort!"a[0]<b[0]"(zip(basedOnThis, alsoSortThis)); This sorts both ranges in-place based on the contents of the first range.
Jun 29 2012
next sibling parent "ixid" <nuaccount gmail.com> writes:
Thank you!
Jun 29 2012
prev sibling parent reply "Ludovit Lucenic" <llucenic gmail.com> writes:
On Friday, 29 June 2012 at 18:00:06 UTC, Timon Gehr wrote:
 On 06/29/2012 07:52 PM, ixid wrote:
 Or more generally does D have a library function so I can sort 
 one array
 based on sorting the contents of another?

sort!"a[0]<b[0]"(zip(basedOnThis, alsoSortThis)); This sorts both ranges in-place based on the contents of the first range.

Hello, I have a similar problem, having statistics per class instance. How would I print out the statistics sorted ? struct TestTuple { ... } int[TestTuple] stats; foreach (test, stat; ??) { writeln(test, " = ", stat); } Please, what comes in ?? ? Your proposal sort!"a[0]<b[0]"(stats) does not compile in this place. Thank you in advance, Ludovit
Sep 05 2013
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Sep 06, 2013 at 08:58:48AM +0200, Ludovit Lucenic wrote:
 On Friday, 29 June 2012 at 18:00:06 UTC, Timon Gehr wrote:
On 06/29/2012 07:52 PM, ixid wrote:
Or more generally does D have a library function so I can sort one
array based on sorting the contents of another?

sort!"a[0]<b[0]"(zip(basedOnThis, alsoSortThis)); This sorts both ranges in-place based on the contents of the first range.

Hello, I have a similar problem, having statistics per class instance. How would I print out the statistics sorted ? struct TestTuple { ... } int[TestTuple] stats; foreach (test, stat; ??) { writeln(test, " = ", stat); } Please, what comes in ?? ? Your proposal sort!"a[0]<b[0]"(stats) does not compile in this place.

[...] You mean you want to sort the stats.keys by the values they are mapped to? What about: import std.array, std.algorithm, std.stdio, std.typecons; // I don't know what your original struct was, this one is just // for example. struct TestTuple { string name; } void main() { int[TestTuple] stats; // Make some sample data for testing stats[TestTuple("test1")] = 10; stats[TestTuple("test2")] = 4; stats[TestTuple("test3")] = 8; stats[TestTuple("test4")] = 11; // Sort by stats. If you want to sort by name instead, // change "a[0] < b[0]" to "a[1] < b[1]". foreach (t; stats.keys .map!((a) => tuple(stats[a], a)) .array .sort!((a,b) => a[0] < b[0])) { auto stat = t[0]; auto test = t[1]; writeln(test, " = ", stat); } } The built-in AA's are inherently unordered, so they cannot be sorted directly. You have to explicitly put the keys / values into an array and sort that. T -- Computers shouldn't beep through the keyhole.
Sep 06 2013
parent "Ludovit Lucenic" <llucenic gmail.com> writes:
On Friday, 6 September 2013 at 16:57:09 UTC, H. S. Teoh wrote:
 You mean you want to sort the stats.keys by the values they are 
 mapped
 to?

Yes, this exactly I wanted to do.
 What about:

 	import std.array, std.algorithm, std.stdio, std.typecons;
 	
 	// I don't know what your original struct was, this one is just
 	// for example.
 	struct TestTuple {
 		string name;
 	}
 	
 	void main() {
 		int[TestTuple] stats;
 	
 		// Make some sample data for testing
 		stats[TestTuple("test1")] = 10;
 		stats[TestTuple("test2")] = 4;
 		stats[TestTuple("test3")] = 8;
 		stats[TestTuple("test4")] = 11;
 	
 		// Sort by stats. If you want to sort by name instead,
 		// change "a[0] < b[0]" to "a[1] < b[1]".
 		foreach (t; stats.keys
 				.map!((a) => tuple(stats[a], a))
 				.array
 				.sort!((a,b) => a[0] < b[0]))
 		{
 			auto stat = t[0];
 			auto test = t[1];
 			writeln(test, " = ", stat);
 		}
 	}

 The built-in AA's are inherently unordered, so they cannot be 
 sorted
 directly. You have to explicitly put the keys / values into an 
 array and
 sort that.


 T

Thank you, your code makes perfect sense. I'm still kinda discovering beauty of D. Ludovit
Sep 07 2013