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$
1
  • 1
    $\begingroup$ Related: (72740) $\endgroup$
    – Mr.Wizard
    Jul 24, 2017 at 14:09

3 Answers 3

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$
6
  • 1
    $\begingroup$ For 5 this gives an extra element as well: Partition[{a, b, c, d, e, f, g}, 5, 2, {1, 2}, {}] $\endgroup$ Jul 24, 2017 at 11:49
  • $\begingroup$ @GeorgeMoore, hope the update ({1,-2} instead of {1,2}) fixes the issue. $\endgroup$
    – kglr
    Jul 24, 2017 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$ Jul 24, 2017 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, 2017 at 12:25
  • $\begingroup$ Thanks, and your edits are helpful. I'll accept this. $\endgroup$ Jul 24, 2017 at 12:37
3
$\begingroup$
Most@Partition[list, 4, 2, 1, {}]

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

$\endgroup$
3
  • 1
    $\begingroup$ Does not work for 5: Most@Partition[{a, b, c, d, e, f, g}, 5, 2, 1, {}] $\endgroup$
    – Kuba
    Jul 24, 2017 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, 2017 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$ Jul 24, 2017 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$
7
  • 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, 2017 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$ Jul 24, 2017 at 11:31
  • $\begingroup$ True. A bit kludgy. I was mainly trying to follow on from the questioner's intuition using UpTo. $\endgroup$ Jul 24, 2017 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$ Jul 24, 2017 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$ Jul 24, 2017 at 11:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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