Я получил официальный ответ от нашивки, нет способа сделать это одним запросом, но есть способ.
1) для учетной записи платформы создается платеж ch_xxxx и связанная транзакция (txn_xxxxxx)
После того, как платформа получает платеж, учетная запись платформы создает перевод на подключенную учетную запись (tr_xxxxxx) и объект переноса также находится на Учетной записи Платформы
2) Когда подключенный аккаунт получил перевод, будет создан платежный объект (py_xxxxxx) и связанная транзакция (txn_xxxxx) На подключенном аккаунте эти платежные транзакции будут сгруппированы вместе и выплачены в виде «po_xxxxxx»
Таким образом, между учетной записью платформы и подключенной учетной записью, от выплаты по подключенной учетной записи к оплате, общий поток выглядит следующим образом:
выплата (po_xxxx) -> транзакции (txn_xxxx) -> платеж (py_xxxx) -> перевод (tr_xxxx) -> оплата (ch_xxxxx)
blockquote>public static void ListTransactionsForPayout(String payout) throws StripeException { //1. Get a list of transactions for payout in Connected account Map<String, Object> balancetransactionParams = new HashMap<String, Object>(); balancetransactionParams.put("limit", 20); balancetransactionParams.put("payout", "po_1Dy8ZfKxxxxxx"); List<String> expandList = new LinkedList<String>(); expandList.add("data.source"); balancetransactionParams.put("expand", expandList); RequestOptions requestOptions = RequestOptions.builder() .setStripeAccount("acct_connected_account") .build(); BalanceTransactionCollection transactions = BalanceTransaction.list(balancetransactionParams, requestOptions); for (BalanceTransaction txn : transactions.autoPagingIterable()) { if (txn.getType().equals("payment")) { Charge charge = (Charge) txn.getSourceObject(); // 2. Get transfers from payment and get charge from transfer Transfer transfer = Transfer.retrieve(charge.getSourceTransfer()); System.out.printf("txn %s -> payment %s -> transfer %s -> charge %s\n", txn.getId(), txn.getSource(), transfer.getId(), transfer.getSourceTransaction()); } } }
Если строка короткая, то простой цикл и тестирование могут быть самым простым и эффективным способом. Я имею в виду, что вы могли бы создать хэш-набор (на любой платформе, которую вы используете) и выполнить итерацию по символам, не пройдя, если символ уже есть в наборе, и добавив его в набор в противном случае - но это только вероятно чтобы обеспечить какую-либо выгоду, когда строки длиннее.
РЕДАКТИРОВАТЬ: Теперь, когда мы знаем, что это отсортировано, ответ mquander является лучшим IMO. Вот реализация:
public static bool IsSortedNoRepeats(string text)
{
if (text.Length == 0)
{
return true;
}
char current = text[0];
for (int i=1; i < text.Length; i++)
{
char next = text[i];
if (next <= current)
{
return false;
}
current = next;
}
return true;
}
Более короткая альтернатива, если вы не возражаете повторить использование индексатора:
public static bool IsSortedNoRepeats(string text)
{
for (int i=1; i < text.Length; i++)
{
if (text[i] <= text[i-1])
{
return false;
}
}
return true;
}
РЕДАКТИРОВАТЬ: Хорошо, со стороной «частоты», я немного переверну проблему. Я все еще собираюсь предположить, что строка отсортирована, поэтому мы хотим узнать длину самого длинного пробега. Если повторов нет, самая длинная длина цикла будет 0 (для пустой строки) или 1 (для непустой строки). В противном случае это будет 2 или более.
Сначала версия для конкретной строки:
public static int LongestRun(string text)
{
if (text.Length == 0)
{
return 0;
}
char current = text[0];
int currentRun = 1;
int bestRun = 0;
for (int i=1; i < text.Length; i++)
{
if (current != text[i])
{
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = text[i];
}
currentRun++;
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Теперь мы также можем сделать это как общий метод расширения в IEnumerable
:
public static int LongestRun(this IEnumerable<T> source)
{
bool first = true;
T current = default(T);
int currentRun = 0;
int bestRun = 0;
foreach (T element in source)
{
if (first || !EqualityComparer<T>.Default(element, current))
{
first = false;
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = element;
}
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Тогда Вы можете вызвать «AABCD». Например, LongestRun ()
.
Сначала версия для конкретной строки:
public static int LongestRun(string text)
{
if (text.Length == 0)
{
return 0;
}
char current = text[0];
int currentRun = 1;
int bestRun = 0;
for (int i=1; i < text.Length; i++)
{
if (current != text[i])
{
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = text[i];
}
currentRun++;
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Теперь мы также можем сделать это как общий метод расширения в IEnumerable
:
public static int LongestRun(this IEnumerable<T> source)
{
bool first = true;
T current = default(T);
int currentRun = 0;
int bestRun = 0;
foreach (T element in source)
{
if (first || !EqualityComparer<T>.Default(element, current))
{
first = false;
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = element;
}
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Тогда Вы можете вызвать «AABCD». Например, LongestRun ()
.
Сначала версия для конкретной строки:
public static int LongestRun(string text)
{
if (text.Length == 0)
{
return 0;
}
char current = text[0];
int currentRun = 1;
int bestRun = 0;
for (int i=1; i < text.Length; i++)
{
if (current != text[i])
{
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = text[i];
}
currentRun++;
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Теперь мы также можем сделать это как общий метод расширения в IEnumerable
:
public static int LongestRun(this IEnumerable<T> source)
{
bool first = true;
T current = default(T);
int currentRun = 0;
int bestRun = 0;
foreach (T element in source)
{
if (first || !EqualityComparer<T>.Default(element, current))
{
first = false;
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = element;
}
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Тогда Вы можете вызвать «AABCD». Например, LongestRun ()
.
Если строка отсортирована, вы можете просто запомнить каждый символ по очереди и убедиться, что следующий символ никогда не будет идентичен последнему символу.
Кроме этого, для строк в десять символов, просто проверка каждого символа против всех остальных, вероятно, так же быстро или быстрее, чем большинство других вещей. Битовый вектор, как предлагает другой комментатор, может быть быстрее (помогает, если у вас небольшой набор допустимых символов.)
Бонус: вот отличное решение LINQ для реализации функциональности Джона:
int longestRun =
s.Select((c, i) => s.Substring(i).TakeWhile(x => x == c).Count()).Max();
Итак, хорошо, это не так очень быстро! У тебя проблема с этим?!
: -)
Поскольку вы используете 3.5, вы можете сделать это в одном запросе LINQ:
var results = stringInput
.ToCharArray() // not actually needed, I've left it here to show what's actually happening
.GroupBy(c=>c)
.Where(g=>g.Count()>1)
.Select(g=>new {Letter=g.First(),Count=g.Count()})
;
Для каждого символа, который отображается более после ввода это даст вам характер и количество случаев.
Это очень быстро скажет вам , если строка содержит дубликаты:
bool containsDups = "ABCDEA".Length != s.Distinct().Count();
Она просто проверяет количество различных символов по сравнению с исходной длиной. Если они разные, у вас есть дубликаты ...
Редактировать: Я думаю, это не заботится о частоте дупликов, которые вы отметили в своем редактировании ... но некоторые другие предложения здесь уже позаботьтесь об этом, поэтому я не буду публиковать код, поскольку отмечу, что некоторые из них уже дают вам достаточно элегантное решение. Мне особенно нравится реализация Джо с использованием расширений LINQ.
Update Now, you'd need an array of counters to maintain a count.
Keep a bit array, with one bit representing a unique character. Turn the bit on when you encounter a character, and run over the string once. A mapping of the bit array index and the character set is upto you to decide. Break if you see that a particular bit is on already.
I think the easiest way to achieve that is to use this simple regex
bool foundMatch = false;
foundMatch = Regex.IsMatch(yourString, @"(\w)\1");
If you need more information about the match (start, length etc)
Match match = null;
string testString = "ABCDE AABCD";
match = Regex.Match(testString, @"(\w)\1+?");
if (match.Success)
{
string matchText = match.Value; // AA
int matchIndnex = match.Index; // 6
int matchLength = match.Length; // 2
}
Как насчет чего-то вроде:
string strString = "AA BRA KA DABRA";
var grp = from c in strString.ToCharArray()
group c by c into m
select new { Key = m.Key, Count = m.Count() };
foreach (var item in grp)
{
Console.WriteLine(
string.Format("Character:{0} Appears {1} times",
item.Key.ToString(), item.Count));
}
/(.).*\1/
(или любой другой эквивалент в синтаксисе вашей библиотеки регулярных выражений)
Не самый эффективный, так как он, вероятно, вернется к каждому символу в строке и затем снова выполнит сканирование вперед. И я обычно не поддерживаю регулярные выражения. Но если вы хотите краткости ...
Хэш-решение, которое описывал Джон, вероятно, лучшее. Вы можете использовать HybridDictionary, так как он хорошо работает с маленькими и большими наборами данных. Где буква - это ключ, а значение - частота. (Обновляйте частоту каждый раз, когда происходит сбой добавления, или HybridDictionary возвращает true для .Contains (ключ))
Когда нет порядка для работы, вы можете использовать словарь для сохранения счетчиков:
String input = "AABCD";
var result = new Dictionary<Char, int>(26);
var chars = input.ToCharArray();
foreach (var c in chars)
{
if (!result.ContainsKey(c))
{
result[c] = 0; // initialize the counter in the result
}
result[c]++;
}
foreach (var charCombo in result)
{
Console.WriteLine("{0}: {1}",charCombo.Key, charCombo.Value);
}