8
$\begingroup$

I would like to use a combination of options of Partition in a way that I can't seem to find in the documentation.

Given example input {a,b,c,d,e,f,g}, I would like output {a,b,c,d},{c,d,e,f},{e,f,g}, i.e. an offset partition where one final element is allowed to be smaller at the end of the list.

Partition[{a,b,c,d,e,f,g}, UpTo[4], 2] 

comes close, but because it continues to run in steps of 2 it gives an extra {g} which I do not want. Using Upto without the offset gives what I want, but I need the offset. Various other combinations get me near but nothing quite fits. I'm aware I could fiddle with this and create some function that goes through and deletes lists that are too small, but Partition has so many nice options that I feel I must be missing something.

Edit: A few people have given answers that work for the given list, but in case I wasn't clear I need this to work for varying partition and offset size and on lists of unknown length, which I really think must be possible.

$\endgroup$
6
$\begingroup$
Partition[{a, b, c, d, e, f, g}, 4, 2, {1, -2}, {}]

{{a, b, c, d}, {c, d, e, f}, {e, f, g}}

Partition[{a, b, c, d, e, f, g}, 5, 2, {1, -2}, {}]

{{a, b, c, d, e}, {c, d, e, f, g}}

In general, a function that works for varying partition and offset size and on lists of unknown length:

ClearAll[pF]
pF = Partition[##, {1, -#3}, {}] &;

Examples:

pF[{a, b, c, d, e, f, g}, 4, 2]

{{a, b, c, d}, {c, d, e, f}, {e, f, g}}

pF[{a, b, c, d, e, f, g}, 4, 3]

{{a, b, c, d}, {d, e, f, g}}

pF[{a, b, c, d, e, f, g}, 5, 2]

{{a, b, c, d, e}, {c, d, e, f, g}}

pF[{a, b, c, d, e, f, g}, 5, 3]

{{a, b, c, d, e}, {d, e, f, g}}

$\endgroup$
  • 1
    $\begingroup$ For 5 this gives an extra element as well: Partition[{a, b, c, d, e, f, g}, 5, 2, {1, 2}, {}] $\endgroup$ – George Moore Jul 24 '17 at 11:49
  • $\begingroup$ @GeorgeMoore, hope the update ({1,-2} instead of {1,2}) fixes the issue. $\endgroup$ – kglr Jul 24 '17 at 11:54
  • $\begingroup$ I know this is in the documentation but I don't fully get it, can you explain what exactly this is doing? I can break it by increasing the offset to 4, but then fix it by using {1,-4} in this case. $\endgroup$ – George Moore Jul 24 '17 at 12:04
  • $\begingroup$ This is from Docs > Partition: the first element of list should appear at position $k_L$ in the first sublist, and the last element of list should appear at or after position $k_R$ in the last sublist The key part is at or after position $k_R$ $\endgroup$ – kglr Jul 24 '17 at 12:25
  • $\begingroup$ Thanks, and your edits are helpful. I'll accept this. $\endgroup$ – George Moore Jul 24 '17 at 12:37
3
$\begingroup$
Most@Partition[list, 4, 2, 1, {}]

{{a, b, c, d}, {c, d, e, f}, {e, f, g}}

$\endgroup$
  • 1
    $\begingroup$ Does not work for 5: Most@Partition[{a, b, c, d, e, f, g}, 5, 2, 1, {}] $\endgroup$ – Kuba Jul 24 '17 at 11:31
  • $\begingroup$ I think it depends on how you interpret the question, esp. "where one final element is allowed to be smaller at the end of the list." If the last list should have at least one distinct element @kglr's answer would be appropriate (and probably it is). $\endgroup$ – eldo Jul 24 '17 at 12:07
  • $\begingroup$ Yeah this is a nice way of saying it and I could have been clearer (though did try), I want to include all the elements of my list somewhere but not have any redundant parts with no unique elements. Thanks a lot. $\endgroup$ – George Moore Jul 24 '17 at 12:40
2
$\begingroup$

An alternative:

Partition[list, UpTo[4], 2, {1, 3}]

{{a, b, c, d}, {c, d, e, f}, {e, f, g}}

Edit: For the more general case, I can't see an easy way to do it directly from Partition. The simplest way I can see (though not necessarily the fastest or most elegant) is, as you suggested, deleting the sublists you don't want.

SeedRandom[1]
n = RandomInteger[{5, 20}];
list = Array[a, n];
offset = RandomInteger[{1, n}];
maxlength = RandomInteger[{offset, n}];
DeleteDuplicatesBy[Partition[list, UpTo[maxlength], offset], Last]

(* {{a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11]}, 
    {a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14]}, 
    {a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17]}, 
    {a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17], a[18]}}

Since DeleteDuplicatesBy will keep the first duplicate, it will only delete the sublists at the end that end with the final element of the list.

$\endgroup$
  • 1
    $\begingroup$ {1, 3} is 4(partition length) dependent so one can't use it as a general fix, unless you explain relation. So Partition[{a, b, c, d, e, f, g}, UpTo@5, 2, {1, 3}] fails. $\endgroup$ – Kuba Jul 24 '17 at 11:28
  • $\begingroup$ Thank you, what exactly is the {1,3} doing here? {1,1} gives my floaty {g} back and {1,2} is the same. $\endgroup$ – George Moore Jul 24 '17 at 11:31
  • $\begingroup$ True. A bit kludgy. I was mainly trying to follow on from the questioner's intuition using UpTo. $\endgroup$ – aardvark2012 Jul 24 '17 at 11:36
  • $\begingroup$ @GeorgeMoore From the documentation, the 1 specifies that a (first element) should appear at position 1 in the first sublist. The 3 specifies that g (the last element) should appear at position 3. Padding is used if necessary, but it isn't in this case because of the UpTo[4]. $\endgroup$ – aardvark2012 Jul 24 '17 at 11:39
  • $\begingroup$ Ah yeah sorry thanks, am so sick of that Partition page now. Can't then see a way to adapt this method to general lists (that I don't know the length of) in a neat way, can you? $\endgroup$ – George Moore Jul 24 '17 at 11:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.