1

I have a piece of code that looks up sub-sentences on Wikipedia if it does not find the full one. My understanding of array slice was, that a negative n argument would start from the end instead of the begging of the array. So I thought I could do some kind of ZigZag iteration on it. But I was wrong. Can someone point me into the right direction?

So I did this:

function splitwords (words, i=0) {
  const parts = words.split(` `);
  const wordcount = parts.length;

  let index = i%((wordcount-1)*2)-(wordcount-1); //zigzag
  let par = parts.slice(index);

  return par;
} 

for (let = 0; i < 10, i++) {
  splitwords('Fresh Prince of Bel Air', i) 
}

My goal would be to this:

Input: 

Fresh Prince of Bel Air

Output:

      Prince of Bel Air
             of Bel Air
                Bel Air
Fresh Prince of Bel
Fresh Prince of
Fresh Prince
Fresh
      Prince
             of
                Bel
                    Air

PS: What is the misconception I have about .slice() ?

meo
  • 30,872
  • 17
  • 87
  • 123
  • https://stackoverflow.com/q/51213210/1048572 https://stackoverflow.com/a/28585563/1048572 – Bergi Apr 29 '21 at 09:45
  • 1
    Make sure to monitor the value of `index`. `slice` works as you say (although you don't use its second argument), but you need to debug... and inspect variables. Also: your desired output does not include "all possible sub sentences". What is the logic to only list these? – trincot Apr 29 '21 at 10:20
  • @trincot I do in reality, I just removed it in the example by mistake, Thanks for getting that. Your right about not having all the possibilities "Prince of Bel" for example is missing. In my case its ok thought, If the function would return it, it would be fine as well, but definitely after the 6 first outputs. – meo Apr 29 '21 at 10:25

2 Answers2

3

So you want all possible slices for a list of words?

function *allSlices(a) {
    for (let i = 0; i < a.length; i++)
        for (let k = i + 1; k < a.length + 1; k++)
            yield a.slice(i, k)
}

let words = 'Fresh Prince of Bel Air'.split(' ')

for (let s of allSlices(words))
    console.log(...s)

If you need them in a different order, it would be easier to keep that additional logic outside of the generator function, for example:

// get all slices first
let slices = [...allSlices(words)]

// use only those that start with the 2nd word
let test = slices.filter(s => s[0] === words[1])
georg
  • 211,518
  • 52
  • 313
  • 390
  • Wow very elegant. Yes kind of but: I do not need the entire sentence and It should start cutting off words in the front. (English has a tendency to have adjectives first, so I want to look for the object in the sentence) – meo Apr 29 '21 at 09:53
  • that's not what I meant. I need to look up "Prince of Bel Air" before I look up "Fresh Prince of Bel". Great function thought. I learned a lot by reading it. Never used a generator function before. – meo Apr 29 '21 at 10:07
  • @meo: you're going to have to give some more examples, because I don't really grasp the logic here. Like, given `A B C D E F G H` where A,B,C are words, what is the desired iteration order? – georg Apr 29 '21 at 10:11
  • you're a beast!!! `B C D E F G H`, `C D E F G H`, `D E F G H`, `E F G H`, `E F G H`, `F G H`, `G H` and only then `B C D E F G`, `B C D E F`, `B C D E` etc,,, – meo Apr 29 '21 at 10:14
  • PS: @nirazul solution has the output in the correct order. – meo Apr 29 '21 at 10:16
2

Although it's not the most beautiful or performant code, this one does the trick and is easily understandable:

const str = "Fresh Prince of Bel Air"
const arr = str.split(' ')
const min = 2
const result = new Set()

// Loop twice for end and start point choice
for (var i = arr.length; i >= min; i--) {
  for (var j = 1; j <= i - min; j++) {
    result.add(arr.slice(j, i).join(' '))
  }
}

// Loop to cut at the end
for (var k = arr.length - 1; k >= min; k--) {
  result.add(arr.slice(0, k).join(' '))
}

// Add all separate words
arr.forEach(item => result.add(item))

for (let item of result) console.log(item);
nirazul
  • 3,928
  • 4
  • 26
  • 46