10
$\begingroup$

So basically you have a table of some values, let's call it a:

a=Table[n,{n,10}];
(*{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}*)

And you want to take the beginning and end parts of the table, within the same line, and do something with them. It is my intention to change them all to 0, but really you could change them to some other variable, say b. We want the parts of the list that do not include some inner values, we'll do {4,5,6} which happen to correspond to the indexes 4 through 6, convenient, no?

a[[Cases[a, (Except[Alternatives @@ Range[4, 6]])]]] = b; a
(*{b, b, b, 4, 5, 6, b, b, b, b}*)

What's a simpler syntax for this? How can we call the end and beginning values of a list in a simpler manner?

a[[Cases[a, (Except[Alternatives @@ Range[4, 6]])]]]
(*{1, 2, 3, 7, 8, 9, 10}*)

The ideal input would be, to me, something like

a[[1;;3;7;;10]]
(*{1, 2, 3, 7, 8, 9, 10}*)

But this gives

(*{7, 8, 9, 10}*)

As expected.

How can we simplify the syntax to call the beginning and end parts of a list, leaving out some chosen middle portion?

$\endgroup$
  • 1
    $\begingroup$ Select[ a, ! MemberQ[ {4, 5, 6}, #] & ] $\endgroup$ – LouisB Aug 11 at 19:23
  • 3
    $\begingroup$ Complement[ a, {4, 5, 6} ] $\endgroup$ – LouisB Aug 11 at 20:02
  • 3
    $\begingroup$ Cheating a little, we could write (a[[#]] = b) & /@ {1 ;; 3, 7 ;; 10}. $\endgroup$ – WReach Aug 11 at 20:39
  • 1
    $\begingroup$ If it's the values, then in Table[n^2,{n,10}] the initial segment would be the span 1 ;; 1 and the final segment would be 3 ;; 10 and the excluded segment (the positions not to be changed) would be 2 ;; 2, if the excluded values were 4, 5, 6 -- no? $\endgroup$ – Michael E2 Aug 11 at 22:48
  • 1
    $\begingroup$ Thanks. I posted an answer. See if I understood correctly. $\endgroup$ – Michael E2 Aug 11 at 23:10
9
$\begingroup$

Update: You can also try MapAt:

a = Range[10];
a = MapAt[b &, a, {{;; 3}, {7 ;;}}]

{b, b, b, 4, 5, 6, b, b, b, b}

Or ReplaceAll

a = Range[10];
a /. Alternatives @@ Drop[a, 4;;6] -> b

{b, b, b, 4, 5, 6, b, b, b, b}

Original answer: Try Drop:

Drop[Range @ 10, {4, 6}]

{1, 2, 3, 7, 8, 9, 10}

Drop[Range @ 10, 4 ;; 6]

{1, 2, 3, 7, 8, 9, 10}

Drop[CharacterRange["a", "j"], {4, 6}]

{"a", "b", "c", "g", "h", "i", "j"}

$\endgroup$
  • 1
    $\begingroup$ Hah, shot myself in the foot with my end question...That works to get the values, but I'm unsure of the readability when we do a[[Drop[Range@10, {4, 6}]]] = b; a. Though, it is a nice implementation and one I had not considered. I'm hoping to find something that is not too over-encumbered, in order to sit in a publication. This is much nicer than the original try of mine, and it only uses the definition of the neglected characters. Quite nice, actually, the more I debate it! Much more general of an approach. +1 $\endgroup$ – CA Trevillian Aug 11 at 19:01
  • $\begingroup$ I've accepted your answer based on these parameters: generality of implementation, multiple versions, & the number of votes. Thank you! $\endgroup$ – CA Trevillian Aug 17 at 2:29
7
$\begingroup$

If it is okay to perform two assignments instead of one, then we can write:

(a[[#]] = b) & /@ {1 ;; 3, 7 ;; 10}

Scan is probably better since it does not bother constructing the result list that we are just going to discard anyway:

Scan[(a[[#]] = b) &, {1 ;; 3, 7 ;; 10}]
$\endgroup$
  • $\begingroup$ Well aaactually--that was the original reason for this question, and I probably could have written that....but I can't remember what cup of coffee I was on at that point! Regardless, this is a great implementation of a pure function applied to an index being used in a functional reassignment. This is technically in one line too, which satisfied my original criteria! Very cool. I wonder if this can be shorted at all for some sort-of code-golf-like...thing...answer? (Hint-hint, but it'd require some user thought) Oooooh scan, yessiree this is a great one, Scan needs more use these days, imo. $\endgroup$ – CA Trevillian Aug 11 at 20:59
6
$\begingroup$

Perhaps this?:

ReplacePart[Range@10, i_ /; Not[4 <= i <= 6] :> b]
(*  {b, b, b, 4, 5, 6, b, b, b, b}  *)
$\endgroup$
  • $\begingroup$ Wow nice!! I like the use of RuleDelayed, am I correct in understanding that you could use either Table[n,{n,10}] or Table[n^2,{n,10}] and we should see the 4th-6th indexed values preserved, as ReplacePart replaces the ith index? The use of Not provides a good deal of readability as well. $\endgroup$ – CA Trevillian Aug 11 at 23:20
  • 2
    $\begingroup$ @CATrevillian Yes, it depends only on the index (part/position), not the value. $\endgroup$ – Michael E2 Aug 11 at 23:23
5
$\begingroup$

By far the simplest way is to do it in two lines:

a = Table[RandomReal[], {n, 10}];
a[[1 ;; 3]] = b;
a[[7 ;; 10]] = b;
a

This gives the output:

{b, b, b, 0.378846, 0.475894, 0.533768, b, b, b, b}

$\endgroup$
4
$\begingroup$

We can use Union[] to perform this operation in a simpler manner:

a[[Range[1, 3] \[Union] Range[7, 10]]]
(*{1, 2, 3, 7, 8, 9, 10}*)

But this is still decently messy, and the readability is not too high. Perhaps someone else has a better method?

a[[Range[1, 3] \[Union] Range[7, 10]]] = b; a
(*{b, b, b, 4, 5, 6, b, b, b, b}*)
$\endgroup$
3
$\begingroup$

For me, the least fussy approach involves using ArrayPad[] twice:

ArrayPad[ArrayPad[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {-3, -4}], {3, 4}, b]
   {b, b, b, 4, 5, 6, b, b, b, b}
$\endgroup$
  • $\begingroup$ Can this be used to rip out the middle portion and present just the edge parts? I suspect so, but I don’t understand this well enough on the surface. Thanks in advance! Very nice usage :) $\endgroup$ – CA Trevillian Aug 12 at 13:07
  • 1
    $\begingroup$ "rip out the middle portion and present just the edge parts" - for that case, I would be using Take[]/Part[] instead. ArrayPad[] is designed to act on both ends of a list, either by adding or removing elements (depending on the signs of the integers used in the second argument). $\endgroup$ – J. M. is away Aug 15 at 5:06
3
$\begingroup$

How about

Range[10] // #[[;; 3]]~Join~#[[7 ;;]] &
$\endgroup$

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.