В следующем примере, который я написал, показано, как
Этот рабочий пример является автономным. Он будет определять простой объект запроса, который использует объект window XMLHttpRequest
для совершения вызовов. Он будет определять простую функцию, чтобы дождаться завершения кучи обещаний.
Контекст. В этом примере запрашивается конечная точка Spotify Web API для поиска объектов playlist
для заданного набора строк запроса:
[
"search?type=playlist&q=%22doom%20metal%22",
"search?type=playlist&q=Adele"
]
Для каждого элемента новый Promise запустит блок - ExecutionBlock
, проанализирует результат, заплатит новый набор обещаний на основе массива результатов, который представляет собой список объектов Spotify user
и выполняет новый HTTP-вызов в ExecutionProfileBlock
асинхронно.
Затем вы можете увидеть вложенную структуру Promise, которая позволяет вам генерировать множественные и полностью асинхронные вложенные HTTP-вызовы и присоединять результаты к каждому подмножеству вызовов через Promise.all
.
NOTE Recent Spotify search
API-интерфейсам потребуется указать токен доступа в заголовках запроса:
-H "Authorization: Bearer {your access token}"
Итак, вы должны запустить следующий пример, вам нужно поместить маркер доступа в заголовки запроса:
var spotifyAccessToken = "YourSpotifyAccessToken";
var console = {
log: function(s) {
document.getElementById("console").innerHTML += s + "
"
}
}
// Simple XMLHttpRequest
// based on https://davidwalsh.name/xmlhttprequest
SimpleRequest = {
call: function(what, response) {
var request;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // Internet Explorer
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch (e) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {}
}
}
// State changes
request.onreadystatechange = function() {
if (request.readyState === 4) { // Done
if (request.status === 200) { // Complete
response(request.responseText)
}
else
response();
}
}
request.open('GET', what, true);
request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken);
request.send(null);
}
}
//PromiseAll
var promiseAll = function(items, block, done, fail) {
var self = this;
var promises = [],
index = 0;
items.forEach(function(item) {
promises.push(function(item, i) {
return new Promise(function(resolve, reject) {
if (block) {
block.apply(this, [item, index, resolve, reject]);
}
});
}(item, ++index))
});
Promise.all(promises).then(function AcceptHandler(results) {
if (done) done(results);
}, function ErrorHandler(error) {
if (fail) fail(error);
});
}; //promiseAll
// LP: deferred execution block
var ExecutionBlock = function(item, index, resolve, reject) {
var url = "https://api.spotify.com/v1/"
url += item;
console.log( url )
SimpleRequest.call(url, function(result) {
if (result) {
var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) {
return item.owner.href;
})
resolve(profileUrls);
}
else {
reject(new Error("call error"));
}
})
}
arr = [
"search?type=playlist&q=%22doom%20metal%22",
"search?type=playlist&q=Adele"
]
promiseAll(arr, function(item, index, resolve, reject) {
console.log("Making request [" + index + "]")
ExecutionBlock(item, index, resolve, reject);
}, function(results) { // Aggregated results
console.log("All profiles received " + results.length);
//console.log(JSON.stringify(results[0], null, 2));
///// promiseall again
var ExecutionProfileBlock = function(item, index, resolve, reject) {
SimpleRequest.call(item, function(result) {
if (result) {
var obj = JSON.parse(result);
resolve({
name: obj.display_name,
followers: obj.followers.total,
url: obj.href
});
} //result
})
} //ExecutionProfileBlock
promiseAll(results[0], function(item, index, resolve, reject) {
//console.log("Making request [" + index + "] " + item)
ExecutionProfileBlock(item, index, resolve, reject);
}, function(results) { // aggregated results
console.log("All response received " + results.length);
console.log(JSON.stringify(results, null, 2));
}
, function(error) { // Error
console.log(error);
})
/////
},
function(error) { // Error
console.log(error);
});
Я подробно рассмотрел это решение здесь .
Самый простой способ добавить и удалить диапазоны в строке - использовать StringBuilder
.
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
Альтернативой является использование String.Substring
, но я думаю, что код StringBuilder
становится более читаемым.
В качестве метода расширения.
public static class StringBuilderExtension
{
public static string SubsituteString(this string OriginalStr, int index, int length, string SubsituteStr)
{
return new StringBuilder(OriginalStr).Remove(index, length).Insert(index, SubsituteStr).ToString();
}
}
Используйте String.Substring()
(подробнее здесь ), чтобы вырезать левую часть, затем вашу замену, затем правую часть. Играйте с индексами, пока не получите правильное значение:)
Что-то вроде:
string replacement=original.Substring(0,start)+
rep+original.Substring(start+rep.Length);
s.Remove(3, 2).Insert(3, "ZX");
-> Это не работает, если строка содержит символ Unicode, такой как Emojis.
С помощью в этом разделе я расширяю класс StringInfo на Replace by position, сохраняя Алгоритм Ник Миллер:
public static class StringInfoUtils
{
public static string ReplaceByPosition(this string str, string replaceBy, int offset, int count)
{
return new StringInfo(str).ReplaceByPosition(replaceBy, offset, count).String;
}
public static StringInfo ReplaceByPosition(this StringInfo str, string replaceBy, int offset, int count)
{
return str.RemoveByTextElements(offset, count).InsertByTextElements(offset, replaceBy);
}
public static StringInfo RemoveByTextElements(this StringInfo str, int offset, int count)
{
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
offset + count < str.LengthInTextElements
? str.SubstringByTextElements(offset + count, str.LengthInTextElements - count - offset)
: ""
));
}
public static StringInfo InsertByTextElements(this StringInfo str, int offset, string insertStr)
{
if (string.IsNullOrEmpty(str?.String))
return new StringInfo(insertStr);
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
insertStr,
str.LengthInTextElements - offset > 0 ? str.SubstringByTextElements(offset, str.LengthInTextElements - offset) : ""
));
}
}
С помощью этого сообщения я создаю следующую функцию с дополнительной проверкой длины
public string ReplaceStringByIndex(string original, string replaceWith, int replaceIndex)
{
if (original.Length >= (replaceIndex + replaceWith.Length))
{
StringBuilder rev = new StringBuilder(original);
rev.Remove(replaceIndex, replaceWith.Length);
rev.Insert(replaceIndex, replaceWith);
return rev.ToString();
}
else
{
throw new Exception("Wrong lengths for the operation");
}
}
Как и другие, упомянутая функция Substring()
существует по какой-то причине:
static void Main(string[] args)
{
string input = "ABCDEFGHIJ";
string output = input.Overwrite(3, "ZX"); // 4th position has index 3
// ABCZXFGHIJ
}
public static string Overwrite(this string text, int position, string new_text)
{
return text.Substring(0, position) + new_text + text.Substring(position + new_text.Length);
}
Также я назначил это против решения StringBuilder
и получил 900 тиков против 875. Так что это немного медленнее.
string s = "ABCDEFG";
string t = "st";
s = s.Remove(4, t.Length);
s = s.Insert(4, t);
Я искал решение со следующими требованиями:
Решение, которое мне больше всего подходит, это:
// replace `oldString[i]` with `c`
string newString = new StringBuilder(oldString).Replace(oldString[i], c, i, 1).ToString();
Используется StringBuilder.Replace(oldChar, newChar, position, count)
Другим решением, которое удовлетворяет моим требованиям, является использование Substring
с конкатенацией:
string newString = oldStr.Substring(0, i) + c + oldString.Substring(i+1, oldString.Length);
Это тоже хорошо. Я угадал , он не так эффективен, как первый из них, из-за ненужной конкатенации строк. Но преждевременная оптимизация - это корень всех злых .
Итак, выберите тот, который вам больше всего нравится:)
Вы можете попробовать что-то связать это:
string str = "ABCDEFGHIJ";
str = str.Substring(0, 2) + "ZX" + str.Substring(5);
Вот метод расширения, который не использует StringBuilder или Substring. Этот метод также позволяет заменяющей строке проходить за длину исходной строки.
//// str - the source string
//// index- the start location to replace at (0-based)
//// length - the number of characters to be removed before inserting
//// replace - the string that is replacing characters
public static string ReplaceAt(this string str, int index, int length, string replace)
{
return str.Remove(index, Math.Min(length, str.Length - index))
.Insert(index, replace);
}
При использовании этой функции, если вы хотите, чтобы вся строка замены заменяла как можно больше символов, установите длину к длине строки замены:
"0123456789".ReplaceAt(7, 5, "Hello") = "0123456Hello"
В противном случае вы можете указать количество символов, которые будут удалены:
"0123456789".ReplaceAt(2, 2, "Hello") = "01Hello456789"
Если вы укажете длину, равную 0 , то эта функция действует так же, как функция вставки:
"0123456789".ReplaceAt(4, 0, "Hello") = "0123Hello456789"
Я думаю, что это более эффективно, поскольку класс StringBuilder не нужно инициализировать и поскольку он использует более основные операции. Пожалуйста, поправьте меня, если я ошибаюсь. :)
Я считаю, что самым простым способом было бы это: (без stringbuilder)
string myString = "ABCDEFGHIJ";
char[] replacementChars = {'Z', 'X'};
byte j = 0;
for (byte i = 3; i <= 4; i++, j++)
{
myString = myString.Replace(myString[i], replacementChars[j]);
}
Это работает, потому что переменную типа string можно рассматривать как массив переменных char. Вы можете, например, обратиться ко второму символу строковой переменной с именем «myString» как myString [1]
Лучше использовать String.substr()
.
Нравится это:
ReplString = GivenStr.substr(0, PostostarRelStr)
+ GivenStr(PostostarRelStr, ReplString.lenght());
Еще один
public static string ReplaceAtPosition(this string self, int position, string newValue)
{
return self.Remove(position, newValue.Length).Insert(position, newValue);
}
string s = "ABCDEFGH";
s= s.Remove(3, 2).Insert(3, "ZX");