January 05, 2014 Re: Simplest way to create an array from an associative array which its contains keys and values? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | Andrej Mitrovic:
> However the [k, aa[k]] expression will allocate an array for each key you iterate over regardless if you use join or joiner. I posted a solution with "only", hope that works. :)
Perhaps the "s" suffix (to define fixed-sized arrays) could avoid that problem:
string[] r = aa.byKey.map!(k => [k, aa[k]]s).join;
Bye,
bearophile
|
January 05, 2014 Re: Simplest way to create an array from an associative array which its contains keys and values? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Sat, Jan 4, 2014 at 1:08 AM, Ali Çehreli <acehreli@yahoo.com> wrote:
> 3) The member rangeFront is needed because Tuple does not have opIndex for dynamic indexes. I can do range.front[0] but I cannot do range.front[currentIndex].
Is there any plan to add indexing on runtime indices to Tuple? It can be done, by generating a specific runtime opIndex for Tuple, if the types held in the tuple have a common type.
CommonType!Types opIndex(size_t index)
{
// generated code, say Types is 3-element long:
switch(index)
{
case 0:
return values[0];
case 1:
return values[1];
case 2:
return values[2];
default:
throw new OutOfRangeException(...);
}
}
|
January 05, 2014 Re: Simplest way to create an array from an associative array which its contains keys and values? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 1/5/14, bearophile <bearophileHUGS@lycos.com> wrote:
> Perhaps the "s" suffix (to define fixed-sized arrays) could avoid
> that problem:
>
> string[] r = aa.byKey.map!(k => [k, aa[k]]s).join;
I would prefer a prefix though, to make it immediately obvious you're creating a static array.
string[] r = aa.byKey.map!(k => s[k, aa[k]]).join;
It's not too bad..
But then again maybe tuples (and some syntax support) is the right
solution for this.
|
January 05, 2014 Re: Simplest way to create an array from an associative array which its contains keys and values? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | On 01/05/2014 03:55 PM, Philippe Sigaud wrote:
> Is there any plan to add indexing on runtime indices to Tuple? It can
> be done, by generating a specific runtime opIndex for Tuple, if the
> types held in the tuple have a common type.
It would override the current index operator.
|
January 05, 2014 Re: Simplest way to create an array from an associative array which its contains keys and values? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Sun, Jan 5, 2014 at 4:49 PM, Timon Gehr <timon.gehr@gmx.ch> wrote:
> On 01/05/2014 03:55 PM, Philippe Sigaud wrote:
>>
>> Is there any plan to add indexing on runtime indices to Tuple? It can be done, by generating a specific runtime opIndex for Tuple, if the types held in the tuple have a common type.
>
>
> It would override the current index operator.
Yes, indeed.
|
January 07, 2014 Re: Simplest way to create an array from an associative array which its contains keys and values? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Gary Willoughby | On Friday, 3 January 2014 at 17:38:16 UTC, Gary Willoughby wrote:
> Simplest way to create an array from an associative array which its contains keys and values?
>
> For example if i have an associative array like this:
>
> ["one":"1", "two":"2"]
>
> What's the easiest way to create a dynamic array that looks like this:
>
> ["one", "1", "two", "2"]
>
> I know it can be done via a loop, but is there a more idiomatic way to achieve this?
As someone with little experience with functional programming, I am just curious - having browsed through the thread - if the various solutions proposed here would really be considered more 'idiomatic' D. Or if they were posted because the OP asked about avoiding the foreach() loop.
In other words while:
auto range = aa.byKey.map!(a => chain(a.only, aa[a].only));
string[] array = range.join;
Saves a few lines of code, and looks cooler, it seems that the trivial foreach loop version is very easy:
string[] array;
foreach (key, value; aa) {
array ~= key;
array ~= value;
}
|
January 07, 2014 Re: Simplest way to create an array from an associative array which its contains keys and values? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Craig Dillabaugh | On Tue, Jan 07, 2014 at 08:38:10PM +0000, Craig Dillabaugh wrote: [...] > As someone with little experience with functional programming, I am just curious - having browsed through the thread - if the various solutions proposed here would really be considered more 'idiomatic' D. Or if they were posted because the OP asked about avoiding the foreach() loop. > > In other words while: > > auto range = aa.byKey.map!(a => chain(a.only, aa[a].only)); > string[] array = range.join; > > Saves a few lines of code, and looks cooler, it seems that the trivial foreach loop version is very easy: > > string[] array; > > foreach (key, value; aa) { > array ~= key; > array ~= value; > } [...] Even better, encapsulate this in a function: CommonType!(K,V)[] aaToArray(K,V)(V[K] aa) if (is(CommonType!(V, K))) { typeof(return) result; foreach (key, value; aa) { result ~= key; result ~= value; } return result; } Then you can use it in a single line next time: string[] arr = aaToArray(["a": "aa", "b" : "bb"]); int[] arr = aaToArray([1: 2, 3: 4]); ... // etc. T -- Real men don't take backups. They put their source on a public FTP-server and let the world mirror it. -- Linus Torvalds |
January 07, 2014 Re: Simplest way to create an array from an associative array which its contains keys and values? | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Tuesday, 7 January 2014 at 20:52:40 UTC, H. S. Teoh wrote:
> On Tue, Jan 07, 2014 at 08:38:10PM +0000, Craig Dillabaugh wrote:
> [...]
>> As someone with little experience with functional programming, I am
>> just curious - having browsed through the thread - if the various
>> solutions proposed here would really be considered more 'idiomatic'
>> D. Or if they were posted because the OP asked about avoiding the
>> foreach() loop.
>>
>> In other words while:
>>
>> auto range = aa.byKey.map!(a => chain(a.only, aa[a].only));
>> string[] array = range.join;
>>
>> Saves a few lines of code, and looks cooler, it seems that the
>> trivial foreach loop version is very easy:
>>
>> string[] array;
>>
>> foreach (key, value; aa) {
>> array ~= key;
>> array ~= value;
>> }
> [...]
>
> Even better, encapsulate this in a function:
>
> CommonType!(K,V)[] aaToArray(K,V)(V[K] aa)
> if (is(CommonType!(V, K)))
> {
> typeof(return) result;
> foreach (key, value; aa) {
> result ~= key;
> result ~= value;
> }
> return result;
> }
>
> Then you can use it in a single line next time:
>
> string[] arr = aaToArray(["a": "aa", "b" : "bb"]);
> int[] arr = aaToArray([1: 2, 3: 4]);
> ... // etc.
>
>
> T
Yes, I would imagine if this was not a 'one off' operation, you would likely want to create a function. That one looks nice.
I posted my question mainly because D advertises itself as a 'multi-paradigm' language. It seems that a number of the more experienced posters on here seem to like functional approaches using the algorithms in std.algorithm.
However, it seems to me sometimes the obvious/simple solution that avoids using std.algorithm results in more readable code. So I was curious to know if using std.algorithm functions are generally considered preferable for simple cases like this, or if it is simply a matter of taste.
As an aside, the trade-off is even more blatant in C++ where a simple hand-rolled solution often comes out looking so much nicer than the STL <algorithm> alternative.
|
January 07, 2014 Re: Simplest way to create an array from an associative array which its contains keys and values? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Craig Dillabaugh | On 1/7/14, Craig Dillabaugh <cdillaba@cg.scs.carleton.ca> wrote:
> In other words while:
>
> auto range = aa.byKey.map!(a => chain(a.only, aa[a].only));
> string[] array = range.join;
>
> Saves a few lines of code, and looks cooler, it seems that the trivial foreach loop version is very easy:
>
> string[] array;
>
> foreach (key, value; aa) {
> array ~= key;
> array ~= value;
> }
OP asked for an array, however the reason I showed the example is because you can get a range that way, which is lazy and will not allocate:
auto items = aa.byKey.map!(a => chain(a.only, aa[a].only)).joiner; //
no allocations at all
writeln(items);
So there's a huge difference, as you're saving memory (and CPU time if you don't want to walk through the entire list).
|
January 07, 2014 Re: Simplest way to create an array from an associative array which its contains keys and values? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Craig Dillabaugh | On Tuesday, 7 January 2014 at 20:38:11 UTC, Craig Dillabaugh wrote:
> Saves a few lines of code, and looks cooler, it seems that the trivial foreach loop version is very easy:
>
> string[] array;
>
> foreach (key, value; aa) {
> array ~= key;
> array ~= value;
> }
Assuming the return value of `byKey` has a length property, using std.array.array has the benefit of automatically allocating just once for the result, while your proposed alternative will grow on demand, causing several allocations that depend on the number of pairs in `aa`.
Of course, Teoh's `aaToArray` can trivially do this too, but the naive loop straight in user code is just that - naive.
|
Copyright © 1999-2021 by the D Language Foundation