【发布时间】:2021-09-11 02:37:08
【问题描述】:
所以这是我面临的一个有趣的问题。我有一个从 ASR 服务器接收到的数组,格式类似于 [{start: 0, end: 0.4, word: "Hello"}, {start: 0.4, end: 0.6, word: "my"}, {start: 0.6, end: 1, word: "name"}]。然后将该数组映射到仅包含单词的字符串数组,例如["Hello", "my", "name"] 最后使用.join(" ") 将该数组转换为字符串,从而生成类似"Hello my name" 的字符串。
问题在于尝试编辑这些值并保持原始数组的格式。我正在使用 React Native TextInput 来允许编辑字符串值。
假设用户想要更改
“你好,我的名字”
到
“你好,我叫”
或
“大声喊出我的名字”
在第一种情况下,需要将数组调整为[{start: 0, end: 0.4, word: "Hello"}, {start: 0.4, end: 0.6, word: "my"}, {start: 0.6, end: 1, word: "name is"}],在第二种情况下,必须将数组调整为[{start: 0, end: 0.4, word: "Bellow"}, {start: 0.4, end: 0.6, word: "my"}, {start: 0.6, end: 1, word: "name"}]。
我完全不知道应该如何处理这个问题。我已经做了大约两个星期了,但仍然不知道。我最近的尝试是映射原始数组,将每个项目的单词值与同一索引处已编辑字符串的单词进行比较。如果它们匹配,我会将它们添加到最终数组中,如果不匹配,我将检查编辑后的字符串中的值是否与我从 Lodash.js 中的 .difference() 函数获得的更改之一匹配。我可能解释得不好,请看一下代码。
const [value, setValue] = useState('');
const findChanges = () => {
let finalWords = [];
// Each of the elements in the currentWords array has three properties: start, end, word
let currentWords = data.words;
if (!Array.isArray(currentWords)) currentWords = JSON.parse(data.words);
// Extract only word strings from currentWords
let currentArr = currentWords.map(x => x.word);
let newArr = value.split(' ');
let currentChangeEndsAt = undefined;
let diff = difference(newArr, currentArr);
const addToFinal = (text: string, startIndex: number, endIndex: number) => {
if (startIndex === endIndex) {
return finalWords.push({ ...currentWords[startIndex], word: text });
}
let start = currentWords[startIndex].start;
let end = currentWords[endIndex].end;
return finalWords.push({ start, end, word: text });
};
currentArr.forEach((word, index) => {
// If index is smaller then we have already handled this word, skip
if (currentChangeEndsAt > index) {
return;
}
// If currentArr item at index matches newArr item at same index, add word to final
if (word === newArr[index]) {
return addToFinal(word, index, index);
}
// If currentArr item at index is one of the the differences
if (diff.indexOf(word) !== -1) {
// Determine recursively at which index the change ends
const changeEndsAt = (searchIndex): number => {
// If next word in currentArr matches the word in newArr at searchIndex return searchIndex
// Else add 1 to searchIndex and recursively call the func again
if (currentArr[index + 1] === newArr[searchIndex]) {
return searchIndex;
} else if (searchIndex === newArr.length - 1) {
return searchIndex;
} else {
return changeEndsAt(searchIndex + 1);
}
};
// Get substring of the change
const endsAt = changeEndsAt(index + 1);
const changeString = newArr.slice(index, endsAt).join(' ');
const endIndex =
endsAt > currentWords.length - 1 ? currentWords.length - 1 : endsAt;
return addToFinal(changeString, index, endIndex);
}
});
return finalWords;
};
正如您所看到的,它非常混乱,您可能会说由于某些原因它无法正常工作。原因之一是如果在字符串函数的开头添加了一个单词,就会崩溃。我曾想过可能实现一个 onChangeText 处理程序,并可能使用 onSelectionChange 回调将 TextInput 的当前光标位置设置为状态,但我无法弄清楚我将如何从那里开始。如果有人对我如何处理这个甚至从哪里开始有任何指示,那将有很大帮助。对于冗长的问题和模糊的标题,我深表歉意,我愿意接受有关改进两者的建议。如果您有更好的想法,请在下面评论。提前致谢。
【问题讨论】:
-
如果将句子修改为简单的“Hello”,您期望得到什么输出?
-
嗨@Gershy,这也是它变得复杂的地方。那么预期的输出将是
[{start: 0, end: 1, word: "Hello"}]。由于录音是固定长度的,因此必须调整开始和结束时间以适应文本。
标签: javascript arrays react-native lodash react-native-textinput